Non, ca, ce n'est pas une bonne optimisation, le compilateur est capable de la faire, et le code est moins lisible.
Tu peux me sortir un benchmark? car pour le moment, dans tout les moteurs nécessitant des performances élever le modulo et la division sont a proscrire au maximum.
Comment es-tu sur à 100% de ce que le compilateur va faire? De la version de ton compilateur? De ton compilateur?
Le code est tout à fait lisible, où il faut revoir ces compétences sur le masquage.
CF : https://software.intel.com/en-us/for...r/topic/298589
Ce genre d'optimisation compte énormément lorsque tu travailles avec un système qui doit rouler rapidement ( Car utiliser par une équipe ) et en debug ( Pour dump les callstacks par exemple ). Je pense à une configuration release avec information de débogage tu as besoin de ce genre de chose.
Après si c,Est pour un logiciel lamba, ça ne fera rien gagné, mais pour la connaissance général il est toujours bon de ne pas oublier ceci.
J'admets une limitation : Le type de "number" doit est unsigned
Je vous retournerais la question : l'optimisation à priori étant la racine de tous les maux, j'attendais d'un bon développeur qu'il écrive if (valeur % 2 == 0) à moins que celui-ci puisse me prouver via profiling que :
- cette instruction en particulier coîte du temps d'exécution
- ET une autre forme soit plus efficace.
Mais vous laissant le bénéfice du doute, et en dépis du fait que je suis persuadé que n'importe quel compilateur décent génère le même assembleur dans les deux cas, j'ai fait le test. Surprise : https://godbolt.org/g/XJcyxw
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 bool f1(int value) { return value % 2 == 0; } bool f2(int value) { return ! (value & 1); }
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 f1(int): mov eax, edi not eax and eax, 1 ret f2(int): mov eax, edi not eax and eax, 1 ret
Passe le sur MSVC 19 2017 RTW sans optimisation pour voir... On ne peut être sur de rien...
Bien sur le compilateur peut optimiser le modulo 2 et heureusement, mais une instruction div en plus est très couteux dans certains cas.
J'ai dit un compilateur décent.
dans certains cas.
Je maintiens donc mes attentes : un bon développeur devrait écrire if (valeur % 2 == 0) à moins que celui-ci puisse prouver via profiling que :
- cette instruction en particulier coîte du temps d'exécution
- ET une autre forme soit plus efficace.
Heu, c'est une blague ??? ou du troll ????sans optimisation
Comparer des performances sans optimisations, c'est sans intérêt.
Certes pour un entier non signé, x % 2 est remplacable par x & 2.
Mais qu'en est-il de x % 4 ?
Et x % 3?
Très bien alors en optimisation complete 'Ox' avec symbol de debug ( même si cela ne change rien ) sous Visual Studio 2015:
Le code suivant:
La version '%' te donne ceci:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 volatile int32 I = 256; { volatile bool IsEven = !(I % 2); IsEven; } { volatile bool IsEven = !(I & 1); IsEven; }
et la version optimisée te donne ceci:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 000007FEE11C6B94 mov eax,dword ptr [I] 000007FEE11C6B9B and eax,80000001h 000007FEE11C6BA0 jge Test::InitializeModule+29h (07FEE11C6BA9h) 000007FEE11C6BA2 dec eax 000007FEE11C6BA4 or eax,0FFFFFFFEh 000007FEE11C6BA7 inc eax 000007FEE11C6BA9 test eax,eax 000007FEE11C6BAB sete byte ptr [rsp+128h]
Donc : la version '&' te permets de t'assurer que peut importe le niveau d'optimisation, de compilateur etc... la version '&' te donne au pire des performances identiques a '%' et au mieux un gain signifiant.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 000007FEE11C6BBB mov eax,dword ptr [I] 000007FEE11C6BC2 xor al,0FFh 000007FEE11C6BC4 and al,1 000007FEE11C6BC6 mov byte ptr [IsEven],al
Une benchmark ne se fait pas sur une simple fonction comme tu as fait, mais sur une version plus complexe comme 90% des cas réels et également dans un environnement multi-thread, etc... donc rigole bien dans ta SSII
Voila ! Vous avez prouvé que sur ce compilateur-ci spécifiquement la réécriture du test a un impact. Si dans un cas concret un besoin d'optimisation se fait sentir et que c'est ce test a un impact significatif, utiliser l'idiome &1 est justifié.
(Ca prouve surtout la qualité de MSVC mais bon...)
Moi pas : https://godbolt.org/g/idQHcm
J'attache beaucoup d'importance à la lisibilité et la simplicité du code. J'ai observé que dans 99% des cas, les développeurs même séniors ont une mauvaise idée de ce qui est "optimisé" et ce qui ne l'est pas. Cela encourage l'écriture de code avec un haut WTF/ligne. Et savez-vous combien coûte une minute passée par un developpeur à essayer de comprendre une ligne inutilement compliquée ? Une fois multiplié par le nombre de lignes farfelues, cela coûte beaucoup, beaucoup plus cher que d'acheter le meilleur cpu du marché pour tous les serveurs du parc.
N'optimisez pas à priori au détriment de la lisibilité, vous aurez tord dans 99% des cas !
Bref, dans le cadre du sous-forum "Débuter en C++" de notre communauté, enseigner la lisibilité est plus important.
Et j'attends encore que tu nous donnes ta version optimisée de x % 3 == 2, c'est à dire un cas réel d'utilisation de modulo.
Permets moi d'émettre beaucoup de réserve sur les sites comme ça comme benchmark...
Le développeur qui ne comprends pas &1 devrait changer de métier.
Et la il n'y a pas tord, &1 te donnera toujours un résultat meilleur ou identique peut importe le compilateur et l'optimisation faite. Donc a moins de travailler dans un SSII comme probablement c'est pas mal le cas ici... Ce genre de choses ont un importance et sont demandées dans certains entretiens...
Et le fait que en debug, le code roule vite à une importance. Je lance souvent en debug une application à déboguer au boulot. Si cette application doit charger des centaines de ressources, decompressé, lire des fichiers etc... la moindre instruction compte et un simple 'F5' sur Visual ce compte en secondes voir minutes.
Donc je m'en contre fou de faire un '%' au lieu d'un '&' si c'est pour une SSII, dans d'autre cas ceci est très important.
Aucun rapport... On cherche à savoir si un entier positif est pair... pas autres choses.Et j'attends encore que tu nous donnes ta version optimisée de x % 3 == 2, c'est à dire un cas réel d'utilisation de modulo.
Un type qui travaille dans une SSII aimerait vous indiquer que sur une architecture en one's complement votre optimisation cassera la fonctionnalité pour les nombres négatifs. Félicitation.
Ho, et c'est vous qui distribuez les pouces rouges comme des petits pains ? :-}
En général, nous sommes complètement à la merci du compilateur et de sa capacité d'optimiser. La plupart des conteneurs de la bibliothèque standart ainsi que ses algorithmes ont un fort niveau d'indirection ; indirection qui disparaît complètement ou quasiment une fois que le compilateur et le linkeur ont fini leur tâche d'optimisation et d'inlining.
Un compilateur décent produira le même code dans les deux cas. Un compilateur non décent produira un binaire aux performances catastrophiques quoi que vous écriviez.
Finalement, envahi par le doute, j'ai cherché sur google "c++ efficient way to test for even number". Je suis rassuré de voir qu'un consensus existe, mais peut être Google ne me montre-t-il que ce que je veux voir. Essayez, et dites-moi ce que vous obtenez s'il-vous-plaît.
Heu, depuis quand la taille de l'assembleur généré est un indicateur fiable des performances d'un code ???
Dans une SSII, on est de la chair à pisser du code, donc les aspects maintenabilités du code sont bien mieux encadrés que des boites où un "cowboy programmeur" peut imposer des merdes à tout le monde parce que : "j'étais là à la création de la boite et je vous emmerde".
Ok, une boite de sodomites des drosophiles, qui se gaussent de leur fatuité.Ce genre de choses ont un importance et sont demandées dans certains entretiens...
On va dire qu'on a envoyé notre CV par mégarde.
C'est pas les boites qui laissent ces pauvres diptères tranquilles qui manquent.
Si on veut vraiment être productif, au lieu de recruter des détraqués sexuels, utilisez des outils d'analyses statiques, c'est plus fiable.
Et si c'est si important, vous pouvez customiser Roslyn pour que le compilateur insulte ce puceau des insectes, qui ose écrire du code lisible.
https://msdn.microsoft.com/fr-fr/lib...or=-2147217396
@Astraya, c'est quand la dernière fois que vous avez essayé de vous faire recruter par une boite ?
Pour l'optimisation sûrement , mais lisibilité je pense que c'est relatif je trouve les 2 lisibles et compréhensibles.Envoyé par ternel
Le ET est peut être moins 'connu' mais il est facilement compréhensible (preuve en l'apprend dans des bac pro ou STI donc loin d’être des bruts en math ! ).
Cela était vrai a une époque ( les divisions/multiplications n'existait pas sur les processeurs ou qu'il prenait trop de cycle ).
Pour les divisions (et je dirait les multiplications aussi) entier ou float , ce n'est plus trop vrai tu peux avoir des divisions/multiplications qui ne te coûte qu'un cycle
Encore plus incroyable , certain processeur permettent de faire des calcul vectoriel/matriciel sur un cycle !
C'est important de le dire , je rajouterait que sans avoir la pipeline en tête d'un processeur donné il est très compliqué de connaître son optimisation réel ! (mais je peux en tout cas dire que le faire manuellement c'est très pénible).Heu, depuis quand la taille de l'assembleur généré est un indicateur fiable des performances d'un code ???
Après il est vrai que le compilateur réfléchira en tout cas moins pour l'instruction ET (tout les processeurs possède l'instruction AND a ma connaissance) pour l'optimisation le compilateur saura choisir.
Je trouve beaucoup de débat pour un truc qui n'en vaut pas la peine , l’optimisation il faut y réfléchir sur du code critique (un truc exécuter 10 000/ 100 000/ 1 000 000 par seconde).
Si pour l'initialisation tu fait du code un peu lent et que tu perd 1 voir 2 cycle bon c'est vraiment s'énerver contre du vent
NT: Alors je me suis renseigné sur le x86 , l'instruction DIV permet de récupérer le modulo et comme de nos jours grâce a la pipeline cette instruction peut être l'équivalent d'un cycle , je crois que vous avez votre réponse
Gameloft, Eidos pour Montréal, Ubisoft et Spider Games pour Paris. Quelques SSII de temps en temps, les pires expériences et les projets les plus merdiques que j'ai jamais rencontré ^^
Je me base sur mon expérience, vous avez la votre. Maintenant pour savoir si un entier positif est pair, '&1' est le meilleur des deux mondes. n'en déplaise à Stack overflow.
Tout comme le fait de faire *0.5 plutôt que /2 est plus efficace... mais bon j'en ai marre de débattre ici de ça
Un très bon document présentant le nombre de micro opération par instruction par processeur: http://www.agner.org/optimize/instruction_tables.pdf
Je ne parle pas de compilateur, car pour ce qui est des optimisations la première règle c'est déjà de ne pas prendre le compilateur pour un génie qui à toujours raison.
Pour ce qui est de ne pas les faire trop tôt, il y a optimisation et optimisation. Changer un * en / et % en & n'est pas en soit un optimisation mais une règle de codage qui permets d'inclure l'optimisation sans avoir à y penser.
Comme quoi on lit les mêmes documents , je trouvais le document intéressant parce que il mettait le nombre de cycle des vieux intel x86 et je voulais le comparer avec celui de la PS2
(Si dans un débat XBOX vs PS2 on sait jamais , ce genre de chiffre ça permet de dire que le processeur de la PS2 était plus balèze :') )
Mais bref ces nombres d'instructions sont 'vrai' mais les processeurs modernes (et la plupart figurant a cette liste ) possède une pipeline.
Par exemple le intel atom fait pour un mul 3 à 8 cycle , mais tu peux faire en sorte qu'il fasse qu'un cycle faut juste qu'il soit pipeliné , alors comment faire ben ça se fait automatiquement il faut juste pas faire une instruction qui arrête sa pipeline(sinon l'instruction coûte plus qu'un cycle).
Alors si tu programme en assembleur ça donnerai que tu devrai avoir a chaque instruction en tète la pipeline et donc avoir une idée de la pipeline pour chaque instruction , t'imagine le truc ? En plus ça t'oblige a réécrire ton code si tu veux faire une modif , parce que oui la modif ça peut chamboulé cette maudite pipeline !
D'ailleurs toute la difficulté du processeur de la PS2 était le VU0 et VU1 outre que c'était des co-processeurs 128 bits , il était superscalaire ,évité les pipeline stall sur deux instructions en même temps c'était comment dire très chiants
Mon but était de réduire l'instruction Div en 1 cycle (elle devait faire 6 cycle sur le VU) , ça permettait au final de faire des calcul de projection 3D/2D(pour l'écran) en quelque cycle !
D'ailleurs je me disait qu'il fallait créer un macro assembleur pour pas ce soucier de cette pipeline , bref de laisser un programme s'occuper de cette optimisation , ah oui ça existe presque deja c'est le C
Alors sur PS2 il existait pas de compilateur C pour ces VU et puis il fallait codé de manière assez bas niveau sur quelque octet alors autant aller en asm , mais il est clair que on passais des heures pour optimiser quelque ligne a la con...
Je dirais qu'en 1995 a cette époque les processeurs ont commencé a avoir une pipeline et tu pouvait bien faire sur ps2 un calcul matriciel en 4 cycle (4 instruction ) et la je parle d'un processeur qui date du siècle dernier (1999).
Et encore je ne connais pas encore tout les processeurs plus récent le CELL (PS3) , les processeur ARM moderne , les X86-64 bits moderne possède encore quelque astuce pour réduire le nombre de cycle (ou éviter d'avoir des conflits sur cette pipeline comme le OoO) , la mémoire cache permet aussi d'avoir des accès mémoire encore plus rapide (et donc réduire le nombre de cycle et donc évité que la pipeline soit pleine).
Bref je suis beaucoup plus réticent d’être si catégorique , si en 1999 on avait la technologie pour faire 1 cycle pour une division ou 4 cycle pour un calcul matriciel (que je codais en asm ) j'ose esperer que 20 ans après on a pas reculé niveau technologie !
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager