J'ai la situation suivante: il y a un énorme ensemble de modèles tels que Si fondamentalement, je pourrais avoir un wrapper: p> mais cela introduirait une vérification d'exécution supplémentaire dans les cas est-il possible d'utiliser __ assume l'indice Pour indiquer au compilateur que si elle sait certainement que code> est zéro, il devrait éliminer le Memmove std :: vecteur code> qui appellera
memmove () code> pour déplacer des parties de la matrice. Parfois, ils voudront "déplacer" des parties de longueur zéro - par exemple, si la queue de tableau est supprimée (comme
std :: vecteur :: effacer () code>), ils voudront bouger Le reste de la matrice em> qui arrivera à avoir une longueur zéro et que zéro sera connu à l'heure de la compilation (j'ai vu le démontage - le compilateur est conscient) mais le compilateur émettra toujours un
Memmove () < / code> appel.
comptage code> est non connu dans la compilation de compilation que je ne veux pas. p>
() code>? p> p>
4 Réponses :
Le point du pour Dans votre cas - le code __ suppose code> est de dire au compilateur d'ignorer des portions du code lors de l'optimisation. Dans le lien que vous avez fourni à l'exemple est donné avec la clause code> par défaut code> du commutateur code> code>. Là, l'indice indique au compilateur que la clause ne sera jamais atteinte, même si théoriquement qu'elle pourrait . Vous dites à l'optimiseur, fondamentalement, «Hé, je sais mieux, jetez ce code». P>
par défaut code> Vous ne pouvez pas l'écrire dans (sauf si vous couvrez toute la plage de la plage de
code> S, qui est parfois problématique) car cela entraînerait une erreur de compilation. Donc, vous avez besoin de l'indice pour optimiser le code vous em> savoir qui est inutile. P>
__ assume code> indice ne vous aidera pas beaucoup. Vous devez vérifier si le nombre
code> est vraiment 0. Sauf si vous êtes sûr qu'il ne peut jamais être rien d'autre que 0, puis ne l'écrivez pas. P>
Cette solution utilise une astuce décrite dans Détection constante de la compilation C ++ - le Trick utilise le temps de compilation entier zéro peut être converti en un pointeur, ce qui peut être utilisé avec une surcharge pour vérifier la propriété "Durée de compilation connue".
#define is_const_0(X) (sizeof(chkconst::chk2(X))<sizeof(chkconst::Big)) #define is_const_pos(X) is_const_0( int(X)^(int(X)&INT_MAX) ) #define is_const(X) (is_const_pos(X)|is_const_pos(-int(X))|is_const_pos(-(int(X)+1)))
Dans toutes les opérations qui prennent des itérateurs externes, la mise en œuvre ne peut pas savoir que les itérateurs remis ne sont pas du même conteneur, et vous ne pouvez donc pas utiliser memcpy code>, et il va de même avec
Effacer Code> (Si vous effacez un élément au milieu et qu'il y a plus de deux éléments au-delà de cela, les gammes sont garanties de chevauchement). Vous pouvez utiliser
memcpy code> d'autre part lorsque vous développez le tampon, car cela garantit que la source et les destinations ne sont pas superposées.
Non, il s'agit d'une résolution de fonction ordinaire, il n'y a même pas de modèle. X (void * A) est utilisé lorsque la valeur est une constante zéro, X (TEMP A) sinon (TEMP peut être construit à partir d'un int, mais ce n'est pas une surcharge préférée pour zéro). Je trouve aussi supercool aussi. La source originale de l'idée semble être Encode.ru/threads/396 -C-compile-time-constant-détection
@shachartooth qui n'est pas Sfinae mais pourrait potentiellement être utilisé à Sfinae. À propos de la réponse, je pense que c'est cool, mais je ne vois pas vraiment comment cela aide le problème. Le principe (comme je l'ai compris) est que le compilateur n'a pas supprimé le si (compte> 0) code> dans un cas où il était connu i> au moment de la compilation pour être 0, Comment changer
compile_time_constant_0> 0 code> à
Tailleof (x)> Tailleof (y) code> affecte comment le compilateur génère le code? (En supposant que 0 est connu à l'heure de la compilation, les deux devraient être également faciles à optimiser) la prochaine question serait la suivante: comment Sharpoth est-il venu à cette conclusion ...
@ Davidrodríguez-Dribeas non, la question était différente - lorsque la condition a été utilisée, si (compte> 0) et Memmove était élue correctement pour connaître zéro, mais si la valeur était encore laissée lorsque la valeur n'était pas compilée, présentant des frais généraux inutiles. . Avec cette solution, il n'y a pas de frais généraux, mais zéro mouvements sont éliminés.
Pourquoi la version GCC est-elle plus complexe?
Je pense que vous avez mal compris la signification de Dans votre cas, si vous l'avez dit à Je ne connais pas la intrinsèque de VS, mais dans GCC, il y a un probable / improbable em> intrinsèque intrinsèque ( __ assumer code>. Il ne dit pas au compilateur de changer son comportement quand il sait em> quelles sont les valeurs, mais cela lui dit plutôt quelles seront les valeurs quand il ne peut pas en déduire lui-même. P>
__ supposer code> que
comptez> 0 code> Il saute le test, comme vous l'avez déjà dit que le résultat sera toujours
True code>, il supprimera la condition et appelle
MemMove code> toujours em>, ce que vous voulez éviter. p>
__ intégré_Expect ((x), 1) code>) qui peut être Utilisé pour indice em> le compilateur sur lequel est le résultat le plus probable du test. Cela ne supprimera pas le test, mais le code de la mise en page de sorte que le plus probable em> (comme dans par votre branche de définition em>) est plus efficace (ne sera pas une branche). P >
Vs n'a rien de probable / peu probable et c'est plutôt triste.
Il me semble que je me souvienne que par défaut, il suppose que la première branche (la si) est prise, ce qui signifie que, si c'est la branche la moins attendue, vous pourriez avoir une incidence sur le code généré en revenant la condition et les clauses if / else
@ David Rodríguez - Dribesas: Cette astuce ne fonctionne pas lorsque vous avez un si code> sans
sinon code>.
si (pas condition) {} else {corps} code>? Ou vous voulez dire que le compilateur générera le même code que dans
si (condition) {corps} code>? Du point de vue de l'emplacement du code, ils généreront la même chose, le code sera juste où le cas échéant est, et il y aura un saut à la fin, mais je ne suis pas sûr que le test / saut sera le même. et / ou si la CPU le traitera différemment
@ David Rodríguez - Dribesas: le compilateur générera en effet le même code pour un si code> sans
sinon code> et pour un
if-ele code> avec vide
Si code> branche.
Si possible de renommer le Memmove, je pense que quelque chose comme ça
ferait - http://codepad.org/s974fp9k Je pense La même chose est probablement possible sans la classe - doit regarder les règles de conversion
Pour le confirmer. p> Aussi, il devrait être possible de surcharger le Memmove d'origine (), par exemple. en passant un
objet (comme Temp (Tailleof (a)) en tant que 3ème argument. P> Vous n'êtes pas sûr de quelle manière serait plus pratique. p> p>
Qu'espérez-vous économiser avec cela? Semble comme une optimisation micro-micro-micro? Vous allez enregistrer deux branches (en regardant la mise en œuvre de base GNU de
MemMove code>)?
@Nim: la ramification, l'appel à
Memmove () code> ainsi que (la partie la plus importante) permettant d'optimiser un code autour du code
Memmove () code> appel - non L'appel signifie que sa préparation des arguments n'est pas nécessaire. Oui, c'est micro, mais cela enregistre des microsecondes.
Essayez-vous de mettre en œuvre votre propre vecteur?
@David Rodríguez - Dribesas: Sorte de - à des fins de formation.
Oh, venez, les gens, Sharmpooth semble avoir suffisamment d'expérience pour savoir que "l'optimisation prématurée est la racine du mal" et que vous ne devriez pas mettre en œuvre votre propre vecteur à moins que vous n'ayez des raisons sérieuses. Il y a des cas où il y a des raisons pour les deux, pensons-nous maintenant que c'est l'une d'entre elles et essayons de résoudre le problème, ne pas le déclarer non problématique.
Il est étrange que le compilateur doit émettre un appel à
Memmove code> lorsqu'il a déjà détecté la longueur 0. En réalité, l'appel doit être inliné, la boucle de taille zéro doit être détectée et élue. Pourquoi cela ne se produit-il pas? Êtes-vous en train de relier contre un runtime dynamique? Si tel est le cas, écrivez un wrapper pour
MemMove code> qui ressemble à ce que vous avez écrit ci-dessus.
@Konrad Rudolph: afaik La raison est que
Memmove () code> est implémenté dans l'assemblage dans les sources d'exécution Visual C ++ et non présentées au compilateur.
@Konradrudolph Memcpy est inliné (en fait "intrinsèces") et le compilateur est suffisamment intelligent pour l'éliminer, mais Memmove n'est pas.
@Suma hm. Une raison pour laquelle? Je me rends compte qu'il est probablement mis en œuvre dans l'assemblage, mais l'optimisation du temps de liaison devrait alors s'occuper de l'affranchissement nécessaire.
@KonraDrudolph Link Time CG ne peut faire aucune optimisation sur les fonctions de montage. Même l'affranchissement d'une fonction d'assemblage n'est pas possible. 1) Vous ne pouvez pas modifier la manière dont les arguments sont transmis, 2) les fonctions se termine déjà avec RET ou éventuellement avec plusieurs RETS, il n'existe pas de manière fiable comment "couper" ce rebut. La mise en œuvre MEMCY est complètement différente, elle est non seulement inline, elle est gérée comme intrinsèque par le compilateur et le compilateur peut utiliser tout ce qu'elle sait de décider de la compilation.
Dupliqué possible de Détection constante de la compilation C ++
@Suma Link-Time Optimisation réécrit le code (il doit, afin de s'intégrer!). Je ne vois pas comment cela diffère de C ++ à l'assemblage. Les deux ne sont que des fichiers d'objet (avec des informations supplémentaires). À moins que, bien sûr, VC ++ ne fournisse pas de distributions de bibliothèque appropriées. Ce serait boiteux.
@Konradrudolph Il est très différent et il y a des informations supplémentaires. LTCG ne fonctionne pas avec un "code natif", mais avec une représentation symbolique du code (c'est pourquoi il doit être activé également lors de la compilation d'objets, non seulement lors de la liaison). Cela ne peut pas être fait de l'assemblage. Voir par exemple msdn.microsoft.com/en-us/magazine/ccc301698.aspx Pour plus d'informations.