J'exprime actuellement la création de fonctions très optimisées et réutilisables pour une bibliothèque de milles. Par exemple, j'écris la fonction "est la puissance de 2" de la manière suivante: Il s'agit d'une implémentation portable et basse-maintenance en tant que modèle en ligne C ++. Ce code est compilé par VC ++ 2008 au code suivant avec les succursales: p> J'ai trouvé aussi la mise en œuvre à partir d'ici: is_power_of_two_fast PROC
test rcx, rcx
je SHORT NotAPowerOfTwo
lea rax, [rcx-1]
and rax, rcx
neg rax
sbb rax, rax
inc rax
ret
NotAPowerOfTwo:
xor rax, rax
ret
is_power_of_two_fast ENDP
4 Réponses :
La seule voie à suivre consiste à reculer un peu et à commencer à regarder l'image plus grande. Soit arrêter la mise en œuvre d'une API micro-optimisée ou de progresser sur la fabrication d'appels d'API plus importants tous optimisés dans MASM64, Yasm, NasM, etc. P>
Si vous utilisez l'un des assembleurs les plus puissants, vous pouvez transformer les petites fonctions en macros, modifiez ainsi la fonction d'assembleur d'en-tête C / C ++ basée sur l'en-tête C / C ++ en un assembleur Inclure le fichier. P>
Non, vous ne pouvez implémenter aucune intrigue personnalisée, elles sont toutes intégrées au compilateur. Ce n'est pas seulement les instructions intégrées, mais le compilateur connaît également la sémantique de l'intrinsèque et adapte le code pour un code environnant différent. P>
Une des raisons de l'assemblage en ligne étant supprimée du X86-64 est que l'insertion de l'assemblage au milieu d'une fonction perturbe l'optimiseur et donne souvent moins de code optimisé sur le code de l'assembleur. Il peut facilement y avoir une perte nette là-bas! P>
Le seul usage réel de l'intrinsique est destiné aux instructions spéciales "intéressantes" que le compilateur ne peut pas générer de constructions C ou C ++, telles que BSF ou BSR. La plupart de tout le reste fonctionnera mieux en utilisant des fonctions inline, comme votre modèle ci-dessus. P>
Si vous avez besoin de faire quelque chose de spécial, le compilateur ne comprend pas, la seule option réelle consiste à écrire la fonction entière sous forme de module d'assembleur séparé. Si l'appel au-dessus de cette fonction est trop coûteux, l'optimisation n'allait probablement pas que beaucoup en premier lieu. P>
Faites confiance à votre compilateur (TM)! p>
VC10 X64 intrinsics ne serait pas d'une grande aide dans ce cas simple.
La ramification dynamique que vous avez est due à l'opérateur && qui est un opérateur de tôt imprimé.
Dans de nombreux cas (votre cas est un exemple parfait) Il est préférable d'éviter la ramification en calculant le résultat pour toutes les branches, puis appliquez un masque pour sélectionner le bon. Un code CPP avec masquage ressemblerait à: dans le code ci-dessus, je ne vérifie pas si le nombre est négatif ou non pour les types signés. Encore une fois, un masque simple fera le tour en effectuant un décalage arithmétique à droite (NUMBIT-1) fois pour obtenir une valeur de (~ 0) pour des nombres négatifs et 0 pour ceux positifs p> p>
Ce que vous suggérez, c'est malheureusement pas très différent de la fonction initiale C ++. Une compilation avec la sortie d'assemblage révèle que VC ++ 2008 utilise l'instruction "Test" lors de la compilation de votre code et les branches sont toujours là.
Même VC 2005 est capable de produire du code avec des instructions SBB.
pour Code C P>
00401000 lea eax,[ecx-1] 00401003 and eax,ecx 00401005 cmp eax,1 00401008 sbb eax,eax 0040100A neg eax 0040100C cmp ecx,1 0040100F sbb ecx,ecx 00401011 add ecx,1 00401014 and eax,ecx 00401016 ret
Mes excuses si c'est une question stupide, mais: non __ DeclSpec (NOINLINE) CODE> signifie qu'il ne peut pas être inlincé par le compilateur, nécessitant la surcharge d'un appel de la fonction (quel op d'envisage pour éviter la version CDB à courir plus vite)?
GCC et ICC permettent toujours l'assemblage en ligne
Évitez la branche en utilisant et au lieu de &&.
@drhirsch: Merci, je garde ça à l'esprit. @Hans Passant: J'ai déjà essayé, mais cela conduit à un code plus lent (trop d'instructions).