-2
votes

C vitesse de comparaison: égale "==" vs bitwise et "&"

Supposons que j'ai un entier qui soit une puissance de 2, par exemple. 1024:

if (b & a) {}


5 commentaires

Vous souhaitez utiliser == comme B & A testera true pour tout ensemble de bits où vous avez les bits correspondants 1 . Écrivez le code en utilisant des comparaisons appropriées et laissez le compilateur à gérer l'optimisation. Voir: Remplacement de "==" avec des opérateurs bitwises


Définir un 1 << n garantit, qu'il n'a que 1 bit défini. Et j'ai lu ce conseil souvent "Laissez le compilateur décider". Mais pour moi, ce conseil est un peu insatisfaisant, quand je veux mieux comprendre les travaux intérieurs. Merci pour le lien.


Je vois ce que vous dites et oui, une puissance de deux n'aura qu'un seul jeu - mais la même chose s'applique - utilisez == et que le compilateur optimise. Le compilateur optimisera à un CMP , puis utilisez un Sete pour fournir le retour dans le cas probable.


A & B ne fera pas ce que vous voulez, mais a ^ b (nié) sera.


Cela dépend de la qualité de votre compilateur et des spécifications de la manière dont la CPU cible implémente la langue d'assemblage en question (n ° de cycles d'horloge par type d'instructions), donc je vais devoir être plus précis.


3 Réponses :


3
votes

Un processeur X86 définit un drapeau en fonction de la façon dont le résultat de toute opération se compare à zéro.

pour le == , votre compilateur utilisera une instruction de comparaison dédiée ou une soustraction, définissant ce drapeau dans les deux cas. Le si () est ensuite implémenté par un saut qui est conditionnel sur ce bit.

pour le & , une autre instruction est utilisée, le logique et l'instruction. Cela aussi définit le drapeau de manière appropriée. Donc, encore une fois, la prochaine instruction sera la branche conditionnelle.

Donc, la question se résume à: existe une différence de performance entre une soustraction et un bitwise et une instruction? et la réponse est "Non" sur une architecture sans saines. Les deux instructions utilisent le même alu, les deux définissent les mêmes drapeaux et cet alu est généralement conçu pour effectuer une soustraction en un seul cycle d'horloge.


Bottom Line: écrire un code lisible et n'essayez pas de microoptimiser ce qui ne peut pas être optimisé.


0 commentaires

4
votes

Ces opérations ne sont même pas équivalentes, car a & b sera faux lorsque a et b B sont 0 . Je suggère donc d'exprimer la sémantique que vous souhaitez (c'est-à-dire a == b ) et laissez le compilateur à l'optimisation.

Si vous Meseur que vous avez des problèmes de performance à ce stade, vous pouvez commencer à analyser / optimiser ...


6 commentaires

Pour être juste, 0 n'est pas une puissance de 2. Alors que vous êtes absolument correct que ces déclarations ne sont pas équivalentes, elles peuvent être techniquement équivalentes pour les pouvoirs de deux. Cela étant dit, je suis d'accord avec la substance de votre point.


@RogueGebanTha, A & B ne fonctionne pas toujours pour même si A est une puissance de 2. Par exemple, envisagez A = 1 << 10; b = (1 << 10) | 1; .


D'accord, cependant, (1 << 10) | 1 n'est plus une puissance de 2.


@ROGUEBUTTHA, l'OP n'a jamais dit B était une puissance de 2.


C'est un point juste! J'ai supposé qu'il voulait dire pour eux les deux, mais oui comme la question est libellée, c'est certainement ne pas me tromper de supposer.


vrai, pour B> A, puis et une déclaration sera vraie. Donc, ma question est vraiment une question noob :)



3
votes

La réponse courte est la suivante: cela dépend de la sorte de choses que vous comparez. Cependant, dans ce cas, je suppose que vous comparez que vous comparez deux variables les unes aux autres (par opposition à une variable et immédiate, etc.)

Ce site , bien que plutôt vieux, étudié combien d'horloges cycles différentes instructions prises sur la plate-forme X86. Les deux instructions que nous sommes intéressées ici sont l'instruction "et" et "l'instruction" CMP "(laquelle utilise le compilateur pour & == respectivement). Ce que nous pouvons voir ici, c'est que ces deux instructions prennent environ 1/3 de cycle - c'est-à-dire que vous pouvez l'exécuter 3 d'entre eux en 1 cycle en moyenne. Comparez ceci à l'instruction "div" qui (en 1996) a pris 23 cycles à exécuter.

Cependant, cela omet un détail important. Une instruction "et" n'est pas suffisante pour compléter le comportement que vous recherchez. En fait, une brève compilation sur X86_64 suggère que vous avez besoin d'une instruction "et" et "test" pour la version "&", tandis que "==" utilise simplement l'instruction "CMP". Parce que toutes ces instructions sont par ailleurs équivalentes dans IPC, le "==" sera en fait légèrement plus rapide ... à partir de 1996.

De nos jours, les processeurs optimisent si bien à la couche métallique nue que vous êtes peu susceptible de remarquer une différence. Cela dit, si vous vouliez voir à coup sûr ... écrivez simplement un programme de test et découvrez-le pour vous-même.

Comme indiqué ci-dessus, même dans le cas où vous avez une puissance de 2, ces instructions ne sont toujours pas équivalentes, car elles ne fonctionnent pas pour 0. Eh bien ... je suppose techniquement zéro n'est pas une puissance de 2. :) Cependant, vous voulez le faire tourner, utilisez "==".


0 commentaires