Pergunta

Que compila para um código mais rápido:"ans = n * 3" ou "ans = n+(n*2)"?

Supondo que n seja int ou long e esteja sendo executado em uma caixa Intel Win32 moderna.

Seria diferente se houvesse alguma desreferenciação envolvida, ou seja, qual destas seria mais rápida?

long    a;
long    *pn;
long     ans;

...
*pn = some_number;
ans = *pn * 3;

Ou

ans = *pn+(*pn*2);

Ou é algo com que não precisamos nos preocupar, já que a otimização dos compiladores provavelmente será responsável por isso em qualquer caso?

Foi útil?

Solução

IMO, essa micro-otimização não é necessária, a menos que você trabalhe com algum compilador exótico.Eu colocaria a legibilidade em primeiro lugar.

Outras dicas

Não importa.Os processadores modernos podem executar uma instrução MUL inteira em um ciclo de clock ou menos, ao contrário dos processadores mais antigos que precisavam realizar uma série de mudanças e adições internamente para executar o MUL, usando assim vários ciclos.eu apostaria que

MUL EAX,3

executa mais rápido que

MOV EBX,EAX
SHL EAX,1
ADD EAX,EBX

O último processador onde este tipo de otimização poderia ter sido útil foi provavelmente o 486.(sim, isso é direcionado aos processadores Intel, mas provavelmente também é representativo de outras arquiteturas).

De qualquer forma, qualquer compilador razoável deve ser capaz de gerar o código menor/mais rápido.Portanto, sempre opte pela legibilidade primeiro.

Como é fácil medir você mesmo, por que não fazer isso?(Usando gcc e time do Cygwin)

/* test1.c */
int main()
{
    int result = 0;
    int times = 1000000000;
    while (--times)
        result = result * 3;
    return result;
}

machine:~$ gcc -O2 test1.c -o test1
machine:~$ time ./test1.exe

real    0m0.673s
user    0m0.608s
sys     0m0.000s

Faça o teste algumas vezes e repita para o outro caso.

Se você quiser dar uma olhada no código assembly, gcc -S -O2 test1.c

Isso dependeria do compilador, de sua configuração e do código circundante.

Você não deve tentar adivinhar se as coisas estão “mais rápidas” sem fazer medições.

Em geral você não deve se preocupar com esse tipo de otimização em nanoescala hoje em dia - é quase sempre uma completa irrelevância, e se você estivesse realmente trabalhando em um domínio onde isso importava, você já estaria usando um criador de perfil e olhando para a saída da linguagem assembly do compilador .

Não é difícil descobrir o que o compilador está fazendo com o seu código (estou usando o DevStudio 2005 aqui).Escreva um programa simples com o seguinte código:

int i = 45, j, k;
j = i * 3;
k = i + (i * 2);

Coloque um ponto de interrupção na linha do meio e execute o código usando o depurador.Quando o ponto de interrupção for acionado, clique com o botão direito no arquivo de origem e selecione "Ir para desmontagem".Agora você terá uma janela com o código que a CPU está executando.Você notará neste caso que as duas últimas linhas produzem exatamente as mesmas instruções, ou seja, "lea eax,[ebx+ebx*2]" (não mudança e adição de bits neste caso específico).Em uma CPU IA32 moderna, provavelmente é mais eficiente fazer um MUL direto em vez de uma mudança de bits devido à natureza de pipeline da CPU, que incorre em uma penalidade ao usar um valor modificado muito cedo.

Isso demonstra o que aku está falando, ou seja, os compiladores são inteligentes o suficiente para escolher as melhores instruções para o seu código.

Depende do compilador que você está realmente usando, mas muito provavelmente eles são traduzidos para o mesmo código.

Você mesmo pode verificar criando um pequeno programa de teste e verificando sua desmontagem.

A maioria dos compiladores é inteligente o suficiente para decompor uma multiplicação inteira em uma série de mudanças e adições de bits.Eu não sei sobre compiladores do Windows, mas pelo menos com o gcc você pode fazer com que ele cuspa o assembler, e se você olhar para isso, provavelmente verá um assembler idêntico para ambas as formas de escrevê-lo.

Isso não importa.Acho que há coisas mais importantes para otimizar.Quanto tempo você investiu pensando e escrevendo essa pergunta em vez de codificar e testar sozinho?

:-)

Contanto que você esteja usando um compilador de otimização decente, apenas escreva código que seja fácil para o compilador entender.Isso torna mais fácil para o compilador realizar otimizações inteligentes.

Você fazer esta pergunta indica que um compilador otimizador sabe mais sobre otimização do que você.Portanto, confie no compilador.Usar n * 3.

Dê uma olhada em esta resposta também.

Os compiladores são bons em otimizar códigos como o seu.Qualquer compilador moderno produziria o mesmo código para ambos os casos e substituiria adicionalmente * 2 por um deslocamento à esquerda.

Confie no seu compilador para otimizar pequenos trechos de código como esse.A legibilidade é muito mais importante no nível do código.A verdadeira otimização deve ocorrer em um nível superior.

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