Question

Qui compile pour un code plus rapide :"ans = n * 3" ou "ans = n+(n*2)" ?

En supposant que n soit un entier ou un long, et qu'il fonctionne sur un boîtier Intel Win32 moderne.

Cela serait-il différent s'il y avait un certain déréférencement, c'est-à-dire lequel de ces éléments serait le plus rapide ?

long    a;
long    *pn;
long     ans;

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

Ou

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

Ou est-ce quelque chose dont il ne faut pas s'inquiéter, car l'optimisation des compilateurs est susceptible d'en tenir compte de toute façon ?

Était-ce utile?

La solution

OMI, une telle micro-optimisation n'est pas nécessaire, sauf si vous travaillez avec un compilateur exotique.Je mettrais la lisibilité en premier lieu.

Autres conseils

Cela n'a pas d'importance.Les processeurs modernes peuvent exécuter une instruction MUL entière en un cycle d'horloge ou moins, contrairement aux processeurs plus anciens qui devaient effectuer une série de décalages et d'additions en interne afin d'exécuter le MUL, utilisant ainsi plusieurs cycles.je parierais que

MUL EAX,3

s'exécute plus rapidement que

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

Le dernier processeur pour lequel ce type d'optimisation aurait pu être utile était probablement le 486.(oui, cela est biaisé en faveur des processeurs Intel, mais est probablement également représentatif d'autres architectures).

Dans tous les cas, tout compilateur raisonnable devrait être capable de générer le code le plus petit/le plus rapide.Alors commencez toujours par la lisibilité.

Comme il est facile de le mesurer soi-même, pourquoi ne pas le faire ?(En utilisant gcc et time de 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

Faites le test plusieurs fois et répétez pour l’autre cas.

Si vous voulez jeter un œil au code assembleur, gcc -S -O2 test1.c

Cela dépend du compilateur, de sa configuration et du code environnant.

Vous ne devriez pas essayer de deviner si les choses vont « plus vite » sans prendre de mesures.

En général vous ne devriez pas vous soucier de ce genre d'optimisation à l'échelle nanométrique de nos jours - c'est presque toujours complètement hors de propos, et si vous travailliez réellement dans un domaine où cela compte, vous utiliseriez déjà un profileur et regarderiez la sortie en langage assembleur du compilateur. .

Il n'est pas difficile de savoir ce que le compilateur fait avec votre code (j'utilise DevStudio 2005 ici).Écrivez un programme simple avec le code suivant :

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

Placez un point d'arrêt sur la ligne médiane et exécutez le code à l'aide du débogueur.Lorsque le point d'arrêt est déclenché, faites un clic droit sur le fichier source et sélectionnez "Aller au démontage".Vous aurez maintenant une fenêtre avec le code que le CPU exécute.Vous remarquerez dans ce cas que les deux dernières lignes produisent exactement les mêmes instructions, à savoir "lea eax,[ebx+ebx*2]" (pas de décalage ni d'ajout de bits dans ce cas particulier).Sur un processeur IA32 moderne, il est probablement plus efficace d'effectuer un MUL direct plutôt que de déplacer des bits en raison de la nature en pipeline du processeur, ce qui entraîne une pénalité lors de l'utilisation trop précoce d'une valeur modifiée.

Cela démontre de quoi parle aku, à savoir que les compilateurs sont suffisamment intelligents pour choisir les meilleures instructions pour votre code.

Cela dépend du compilateur que vous utilisez réellement, mais ils se traduisent très probablement par le même code.

Vous pouvez le vérifier vous-même en créant un petit programme de test et en vérifiant son démontage.

La plupart des compilateurs sont suffisamment intelligents pour décomposer une multiplication entière en une série de décalages et d'ajouts de bits.Je ne connais pas les compilateurs Windows, mais au moins avec gcc, vous pouvez lui faire cracher l'assembleur, et si vous regardez cela, vous pouvez probablement voir un assembleur identique pour les deux façons de l'écrire.

Cela s'en fiche.Je pense qu'il y a des choses plus importantes à optimiser.Combien de temps avez-vous consacré à réfléchir et à rédiger cette question au lieu de coder et de tester par vous-même ?

:-)

Tant que vous utilisez un compilateur d'optimisation décent, il suffit écrire du code facile à comprendre pour le compilateur.Cela permet au compilateur d'effectuer plus facilement des optimisations intelligentes.

Vous posez cette question indique qu'un compilateur d'optimisation en sait plus sur l'optimisation que vous.Alors faites confiance au compilateur.Utiliser n * 3.

Jettes un coup d'oeil à cette réponse aussi.

Les compilateurs sont efficaces pour optimiser un code tel que le vôtre.Tout compilateur moderne produirait le même code dans les deux cas et remplacerait en plus * 2 par un décalage vers la gauche.

Faites confiance à votre compilateur pour optimiser de petits morceaux de code comme celui-là.La lisibilité est beaucoup plus importante au niveau du code.La véritable optimisation devrait venir à un niveau supérieur.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top