Ce qui est plus rapide : si (bool) ou si(int)?
Dont la valeur est préférable d'utiliser? Boolean true ou un Entier de 1?
Le thème m'a fait faire quelques expériences avec bool
et int
dans if
condition. Donc, juste par curiosité, j'ai écrit ce programme:
int f(int i)
{
if ( i ) return 99; //if(int)
else return -99;
}
int g(bool b)
{
if ( b ) return 99; //if(bool)
else return -99;
}
int main(){}
g++ intbool.cpp -S
génère asm code pour chacune des fonctions comme suit:
-
asm code pour
f(int)
__Z1fi: LFB0: pushl %ebp LCFI0: movl %esp, %ebp LCFI1: cmpl $0, 8(%ebp) je L2 movl $99, %eax jmp L3 L2: movl $-99, %eax L3: leave LCFI2: ret
-
asm code pour
g(bool)
__Z1gb: LFB1: pushl %ebp LCFI3: movl %esp, %ebp LCFI4: subl $4, %esp LCFI5: movl 8(%ebp), %eax movb %al, -4(%ebp) cmpb $0, -4(%ebp) je L5 movl $99, %eax jmp L6 L5: movl $-99, %eax L6: leave LCFI6: ret
Étonnamment, g(bool)
génère plus de asm
instructions! Ça veut dire que if(bool)
est peu plus lent que if(int)
? J'ai l'habitude de penser que bool
est particulièrement conçu pour être utilisé dans l'instruction conditionnelle telle que if
, donc je m'attendais à g(bool)
à générer moins de asm instructions, ce qui rend g(bool)
plus efficace et rapide.
EDIT:
Je ne suis pas en utilisant toute option d'optimisation à partir de maintenant. Mais même en l'absence de cela, pourquoi est-il générer plus d'asm pour g(bool)
est une question pour laquelle je suis à la recherche d'une réponse raisonnable. Je dois aussi vous dire que -O2
option d'optimisation génère exactement le même à l'asm. Mais ce n'est pas la question. La question est de savoir ce que j'ai demandé.
- dépend si cmpb est plus rapide que cmpl
- Il est également injuste de test à moins de les comparer avec raisonnable optimisations activées.
- Je ne suis pas en utilisant toutes les options d'optimisation avec l'un d'eux. Mais même en l'absence de celui-ci, pourquoi ne génère plus d'asm pour
g(bool)
est une question pour laquelle je suis à la recherche d'une réponse raisonnable. - Si il n'y a aucun code entre accolades en suivant les instruction si, alors ... la réponse est.... ils sont les mêmes.
- Je vous suggère d'utiliser -O3, mais assurez-vous que le compilateur n'est pas seulement en ligne et annuler votre code car il n'a aucun effet pour le moment. 😛
- Je pense aussi que cela dépend de l'architecture et du compilateur
- Voir le montage 😀
- C'est ça le problème. Une version peut, pour les extérieurs, de la raison, de générer du code qui prend un couple de plus d'instructions lors de la compilation sans optimisations, mais une meilleure mesure de la valeur intrinsèque de la vitesse de l'essai de type int ou bool serait de comparer les deux compilé avec-O. Sans optimisations, vous êtes seulement de tester lequel est le plus directement traduit dans le compilateur de la représentation intermédiaire(s).
- Aussi, est-il déplacer le bool sur l' %eax% s'inscrire car il n'est pas la taille de mot? En comparaison à l'int, qui est la taille de mot donc c'est un de moins optimisation; ce qui aurait sûrement été fait si l'optimisation des appartements ont été activés.
- Pourquoi voudriez-vous aller à la peine de lire l'asm, mais pas seulement d'exécuter le programme et le calendrier de la suite? Le nombre de instructiosn n'est pas vraiment en dire beaucoup sur les performances. Vous avez besoin de prendre en compte non seulement l'instruction des longueurs, mais aussi les dépendances et les types d'instructions (certains d'entre eux sont décodés à l'aide de la plus lente de microcode chemin d'unités d'exécution vous demandent-ils, qu'est-ce que le temps de latence et le débit de l'instruction, est-il une branche? Un memmory accès?
- pourquoi ne génère plus d'asm pour
g(bool)
est une question pour laquelle je suis à la recherche d'une réponse raisonnable" c'est pas ce Que dit le titre. - a) Pour toute raisonnable de travailler votre code sera plus jamais le faire, la différence de temps entre si (bool) ou si (int) doit être la plupart du temps inutiles. Écrire un code lisible. b) Écrire un environnement de test, d'où vous venez de passer dans les 2 alternatives d'une fonction, ce qui vous donne avec des données empiriques de 1 à 10 programme s'exécute avec 1000 à 1000000000 cas avec les différents paramètres du compilateur et des compilateurs différents - par la fabrication et de la version et de regarder votre micro-benchmarks vous-même.
- inconnu,et @Malvolio: C'est évidemment; je ne suis pas le faire toutes ces, pour la production de code. Comme je l'ai déjà mentionné au début de mon post que "Donc, juste par curiosité, j'ai écrit ce programme". Donc ouais, c'est purement hypothétique.
- C'est une question légitime. Ils sont soit équivalentes ou l'un est plus rapide. L'ASM a probablement été publié dans une tentative d'être utile ou de penser à voix haute, alors plutôt que de l'utiliser comme un moyen d'esquiver la question et de dire "il suffit d'écrire un code lisible", il suffit de répondre à la question ou STFU si vous ne savez pas ou n'avez pas quelque chose à en dire 😉 Ma contribution, c'est que la question est responsable, et "il suffit d'écrire un code lisible" n'est rien mais une esquive de la question.
Vous devez vous connecter pour publier un commentaire.
Fait sens pour moi. Votre compilateur définit apparemment un
bool
comme une valeur de 8 bits, et votre système ABI oblige à "promouvoir" petite (< 32-bit) arguments entiers de 32 bits lorsque l'on pousse sur la pile d'appel. Donc, pour comparer unbool
, le compilateur génère le code pour isoler l'octet le moins significatif de l'32 bits argument que g reçoit, et le compare aveccmpb
. Dans le premier exemple, leint
argument utilise l'intégralité de 32 bits qui ont été poussés sur la pile, de sorte qu'il compare simplement contre le tout aveccmpl
.__int64
est plus rapide queint
? Ou CPU traite entier de 32 bits 32 bits des jeux d'instructions séparément?De la compilation avec
-03
donne pour moi:f:
g:
.. donc il compile essentiellement le même code, sauf pour
cmpl
vscmpb
.Cela signifie que la différence, si il y a de tout, n'a pas d'importance. À en juger par unoptimized code n'est pas juste.
Modifier pour clarifier mon point de vue. Unoptimized code est simple pour le débogage, pas pour la vitesse. Comparant la vitesse de unoptimized code est absurde.
-O2
est plus que suffisant, car il génère le même asm (qui je l'ai mentionné dans l'ÉDITION).cmpl
pour l'un etcmpb
pour les autres?bool
est un octet et unint
est de quatre. Je ne pense pas qu'il n'y a rien de plus spécial que ça.bool
8 bits type.bool
est un bit, pas d'un octet.char
, qui est un octet par définition, et est la plus petite unité adressable.bool
's la taille de la mise en œuvre est définie par, et peut être de 1, 4, ou 8, ou quoi que ce soit. Les compilateurs ont tendance à en faire un, cependant.-g
a été simple pour le débogage.-g
est réellement bon pour faire de gcc émettre des informations de débogage, mais il devient de plus en plus inutile que l'optimiseur de niveau est augmenté. Le manuel de gcc met gentiment:GCC allows you to use -g with -O. The shortcuts taken by optimized code may occasionally produce surprising results
.Quand je compile ce avec un esprit sain ensemble d'options (plus précisément -O3), voici ce que j'obtiens:
Pour
f()
:Pour
g()
:Ils continuent à utiliser des instructions différentes pour la comparaison (
cmpb
booléenne vscmpl
pour int), mais sinon le corps sont identiques. Un rapide regard sur les manuels Intel me dit: ... pas grand-chose. Il n'y a pas une telle chose commecmpb
oucmpl
dans les manuels Intel. Ils sont touscmp
et je ne trouve pas le calendrier des tables à l'heure actuelle. Je suppose, cependant, qu'il n'y a pas d'horloge différence entre la comparaison d'un octet immédiate contre la comparaison d'une longue immédiat, donc, à toutes fins pratiques, le code est identique.modifié pour ajouter les options suivantes en fonction de votre plus
La raison pour laquelle le code est différent dans le unoptimized cas, c'est qu'il est unoptimized. (Oui, elle est circulaire, je sais). Lorsque le compilateur promenades de l'AST et génère le code directement, il ne sait pas" n'importe quoi sauf ce qui est au point de l'AST c'est dans. À ce stade, il est dépourvu de toute information contextuelle nécessaire de savoir que, à ce point précis, il peut traiter le type déclaré
bool
comme unint
. Un booléen est évidemment par défaut traitée comme un octet, et lors de la manipulation des octets dans le Intel monde que vous avez à faire des choses comme le signe-s'étendre à apporter à certaines largeurs de le mettre sur la pile, etc. (Vous ne pouvez pas pousser un octet.)Lorsque l'optimiseur de vue de l'AST et de la magie, cependant, il ressemble au contexte environnant et "sait" quand il peut remplacer le code avec quelque chose de plus efficace sans changer la sémantique. Donc, il "sait", il peut utiliser un entier en paramètre et perdre ainsi les conversions inutiles et l'élargissement de l'.
l
etb
sont les suffixes utilisés dans le AT&T syntaxe seul. Ils suffit de voir versions decmp
à l'aide de 4 octets (de long) et 1 octet (byte) opérandes respectivement. Où il y a une ambiguïté dans la syntaxe intel, conventionnellement la mémoire opérande est taggés avecBYTE PTR
,WORD PTR
ouDWORD PTR
au lieu de mettre un suffixe sur l'opcode.cmp
ont le même rendement, et il n'y a aucune partiel-registre des sanctions pour lecture%dil
. (Mais cela ne veut pas arrêter le bruit de manière amusante la création d'un partiel-registre de décrochage en utilisant la taille en octetsand
sur AL dans le cadre de branchlessly cas de basculement entre 99 et -99.)Avec GCC 4.5 sur Linux et Windows au moins,
sizeof(bool) == 1
. Sur x86 et x86_64, vous ne pouvez pas passer en moins d'un registre de la valeur à une fonction (que ce soit via la pile, un registre, selon la convention d'appel, etc...).De sorte que le code pour le type bool, lorsque non optimisée, va en réalité à une certaine longueur d'extraire une valeur booléenne à partir de l'argument de la pile (à l'aide d'un autre logement de la pile, pour économiser de l'octet). C'est plus compliqué que de simplement en tirant un natif de registre de taille variable.
sizeof(bool)
etsizeof(wchar_t)
sont définis par l'implémentation." ce disantsizeof(bool) == 1
n'est pas strictement exact, sauf si vous parlez d'une version spécifique d'un compilateur spécifique.Au niveau de la machine il n'y a pas une telle chose comme bool
Très peu de jeu d'instructions architectures de définir toute sorte d'opérande booléen type, bien qu'il existe souvent des instructions afin de déclencher une action sur des valeurs non nulles. Pour le PROCESSEUR, généralement, tout ce qui est l'un des types scalaires ou une chaîne d'eux.
Un compilateur et un ABI aurez besoin de choisir des tailles spécifiques pour
int
etbool
et lorsque, comme dans votre cas, ces sont de tailles différentes, ils peuvent générer du code légèrement différent, et à certains niveaux de l'optimisation, on peut être un peu plus rapide.Pourquoi est-bool d'un octet sur de nombreux systèmes?
Il est plus sûr de choisir un
char
type bool parce que quelqu'un peut faire une très grande foule.Mise à jour: par "plus sûr", je veux dire: pour le compilateur et de la bibliothèque des réalisateurs. Je ne dis pas que les gens ont besoin de ré-écrire le type de système.
bool
étaient représentés par des bits; de sorte octet sera un bon compromis pour la vitesse des données/de la compacité dans de nombreuses implémentations.char
au lieu debool
", mais simplement "char
type" pour dire "1 byte" en se référant à la taille, le compilateur choisit pourbool
objets.Ouais, la discussion est amusant. Mais il suffit de tester:
Code de Test:
Compilé sur une version 64 bits de Ubuntu 10.10 ordinateur portable avec:
g++ -O3-o /tmp/test_i /tmp/test_i.cpp
Entier de comparaison:
Boolean test /imprimer sans commentaire (entier et commenté):
Ils sont les mêmes avec 1 affectation et 2 comparaisons chaque boucle de plus de 30 millions de boucles. Trouver quelque chose d'autre à optimiser. Par exemple, ne pas utiliser strcmp inutilement. 😉
Il va surtout dépendre du compilateur et de l'optimisation. Il y a une discussion intéressante de la langue (agnostique) ici:
Ne "si ([bool] == true)" nécessitent une étape de plus que "si ([bool])"?
Aussi, jetez un oeil à ce post: http://www.linuxquestions.org/questions/programming-9/c-compiler-handling-of-boolean-variables-290996/
Aborder la question de deux façons différentes:
Si vous êtes particulièrement parler de C++ ou de tout langage de programmation qui va produire assemblée de code pour cette question, nous sommes liés à ce code que le compilateur va générer dans l'ASM. Nous sommes également liés à la représentation du vrai et du faux en c++. Un entier devra être stocké en 32 bits, et je pourrais simplement utiliser un octet pour stocker l'expression booléenne. Asm extraits de code pour les instructions conditionnelles:
Pour l'entier:
Pour le bool:
C'est pourquoi la comparaison de la vitesse est donc dépendante de la compilation. Dans le cas ci-dessus, le bool serait un peu rapide depuis
cmp
impliquerait une soustraction pour fixer les drapeaux. Il contredit également à ce que votre générés par le compilateur.Une autre approche, une autre beaucoup plus simple, est à chercher dans la logique de l'expression sur son propre et n'essayez pas à vous soucier de la façon dont le compilateur va traduire votre code, et je pense que c'est une bien meilleure façon de penser. Je persiste à croire, en fin de compte, que le code généré par le compilateur est en fait en essayant de donner une véritable résolution. Ce que je veux dire, c'est que, peut-être si vous augmentez le cas de test dans l'instruction if et le bâton avec booléenne d'un côté entier d'une autre, le compilateur fera en sorte que le code généré s'exécuter plus rapidement avec des expressions booléennes au niveau de la machine.
Je suis en train d'étudier est un modèle conceptuel de question, donc je vais donner un modèle conceptuel de réponse. Cette discussion me rappelle les discussions que j'ai souvent ont quant à savoir si ou non le code d'efficacité se traduit par moins de lignes de code dans l'assemblée. Il semble que ce concept est généralement accepté comme étant vrai. Considérant que garder une trace de la façon dont rapidement l'ALU va traiter chaque instruction n'est pas viable, la deuxième option serait de se concentrer sur les sauts et les compare à l'assemblée. Lorsque c'est le cas, la distinction entre les déclarations booléennes ou entiers dans le code devient assez représentative. Le résultat d'une expression en C++ renvoie la valeur qui sera ensuite donné une représentation. Dans une assemblée, d'autre part, les sauts et les comparaisons seront en fonction des valeurs numériques quel que soit le type de l'expression est évaluée de retour à vous C++ si l'instruction. Il est important, sur ces questions, de se rappeler que purement logicical états tels que ceux-ci se retrouvent avec un énorme calcul des frais généraux, même si un seul bit serait capable de la même chose.