Pergunta

Isenção de responsabilidade:Eu não sou um compilador especialista.Eu sou apenas curioso e vêm buscando a iluminação.

Eu tenho visto pessoas afirmam que -- para a eficiência -- for loops, geralmente, devem usar um zero de comparação para o término do contrato.Assim, em vez de:

void blink1(int n) {
    for (int i=0; i<n; i++) {
        blink_led();
    }
}

você deve escrever:

void blink2(int n) {
    for (int i=n; i>0; i--) {
        blink_led();
    }
}

Eu pensei que era um pouco bobo:por que colocar o peso sobre o ser humano se um compilador poderia interpretar ambos os casos como "blink_led() n vezes"?

Mas usando O sr.Godbolt do Compilador Explorer, Agora eu acho que eu estou errado.Para todos os compiladores que eu tentei, o "compare contra zero" sempre produziram um curto circuito.Por exemplo, x86-64 gcc 10.2-O3 otimização produziu o seguinte presilhas internas:

blink1:
    ...
.L3:
        xor     eax, eax
        add     ebx, 1
        call    blink_led
        cmp     ebp, ebx
        jne     .L3

vs

blink2:
    ...
.L12:
        xor     eax, eax
        call    blink_led
        sub     ebx, 1
        jne     .L12

Portanto, eis a questão

Isso parece como um caso comum.

Por que não pode (ou não) o compilador notar que o efeito do for loop é simplesmente "fazer isso" N "vezes" -- se a contagem ou a contagem regressiva -- e otimizar para que?

Foi útil?

Solução

O que você lê é absurdo total, exceto para o mais primitivo dos compiladores.Primeiro, a comparação com um número inteiro é tão rápido, possivelmente, até mesmo mais rápido do que a comparação com uma constante.Em segundo lugar, uma boa optimização do compilador vai demorar um loop escrito usando algum padrão comum e transformá-lo no melhor código possível;ele pode não reconhecer a sua ofuscado padrão e produzir menos código para ele.

E por último, você não deve substituir legível com um código ilegível, a menos que haja uma necessidade real para ele.Se você passar uma hora fazendo a mudança, a produção de 20 horas salvo o tempo de CPU pelo menos.Quando você está naquele nível, melhor algoritmos são muito propensos a dar o melhor de poupança.

Outras dicas

Eu acho que concordo principalmente com o @gnasher729, mas aquelas pessoas que se preocupar com a "eficiência" critica usando o loop for em tudo -- o "eu" variável não adiciona nada ...

Por que não:

void blink3(int n) {
    while (n-- > 0) {
       blink_led();
    }
}

Eu adicionei o "> 0" para um par de razões:1) apenas no caso de alguém que pede para um valor NEGATIVO de piscar, não quero andar para trás para 2 bilhões de vezes.2) é um pouco mais evidente para o unitiated (talvez).

Pelo caminho, no exemplo imaginário, o "blink_led()" função é estranho e suspeito -- provavelmente vai esperar para ser capaz de vê-lo ir, em seguida, desligado.Assim, a "eficiência" é um pouco fora da mesa.

Mas, em geral, para a maioria das coisas, a eficiência é principalmente sobre o quão rápido ele pode ser codificado e também (o mais importante) o quão rápido ele é compreendido.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a cs.stackexchange
scroll top