J'utilise l'extension de vecteur Simd GCC pour un projet, tout fonctionne assez bien mais jette simplement, ils réinitialisent simplement tous les composants d'un vecteur.
the manuel états: p>
Il est possible de lancer d'un type de vecteur à un autre, à condition qu'ils soient de la même taille (en fait, vous pouvez également lancer des vecteurs vers et à partir d'autres types de données de la même taille). P> blockQuote>
Voici un exemple simple: p>
xxx pré> compilation avec
GCC Cast.c -O3 -O coule code> et exécuté sur ma machine Je reçois: p>
xxx pré> Je ne suis pas ce garu assembleur mais je viens de voir quelques mouvements d'octets ici: p>
xxx pré> i Suspectez l'équivalent de vecteur du scalaire: p>
xxx pré> Comment pouvez-vous expliquer ce comportement? p> p>
3 Réponses :
C'est ce que les moulages de vecteur sont définis à faire (tout ce qui serait complètement bonkers et ferait des idiomes de programmation vectorielle standard très douloureux à écrire). Si vous voulez réellement obtenir une conversion, vous voudrez probablement utiliser un intrinsèque d'une sorte, comme _MM_CVTEPI32_PS (cela enfreint la belle indépendance architecturale de votre code de vecteur, ce qui est également ennuyeux; une approche commune est d'utiliser une en-tête de traduction qui définit un ensemble portable de "intrinsics"). P>
Pourquoi est-ce utile? Une variété de raisons, mais voici le plus grand: p>
Dans le code de vecteur, vous ne voulez presque jamais brancher. Au lieu de cela, si vous avez besoin de faire quelque chose de conditionnellement, vous évaluez les deux côtés de la condition et utilisez un masque pour sélectionner la voie de résultat appropriée de la voie. Ces vecteurs de masque "naturellement" ont un type d'entier, alors que vos vecteurs de données sont souvent des points flottants; Vous voulez combiner les deux opérations logiques. Cet idiome extrêmement courant est le plus naturel si les lancers de vecteur réintroduisent simplement les bits. P>
accordé, il est possible de contourner ce cas, ou n'importe lequel d'un sac d'autres idiomes de vecteur commun, mais le vecteur est un sac de bits "est extrêmement courant et reflète la façon dont la plupart des programmeurs vectoriels pensent. p>
En fait, aucune instruction vectorielle unique n'est même générée dans votre cas et qu'aucun document n'est même pas effectué au moment de l'exécution. Tout cela s'est fait lors de la compilation en raison du commutateur Le pointeur sur la chaîne de format est de classe -O3 code>. Les quatre
MOVSD code> sont en train de charger les arguments préconvertis sur
printf code>. En effet, selon le SYSV AMD64 ABI, des arguments à virgule flottante sont transmis dans les registres XMM. La section que vous avez désassemblée est (code d'assemblage obtenu en compilant avec
-s code>):
.LC5 code> étiquette la chaîne de format: p>
integer code> et est donc transmis dans le registre
rdi code> registre (être quelque part Dans la première 4 gibières de l'espace VA, certains octets de code sont enregistrés en émettant un déplacement 32 bits à la partie inférieure de
RDI code>). Registre
RAX code> (
EAX code> utilisé pour enregistrer les octets de code) est chargé avec le nombre d'arguments transmis dans les registres XMM (à nouveau en fonction de l'ABI SYSV AMD64 pour les appels aux fonctions avec des fonctions avec nombre variable d'arguments). Tous les quatre
MOVSD CODE> (déplacez la double précision scalaire) Déplacez les arguments correspondants dans les registres XMM.
.LC9 code> par exemple étiquettes Deux Motswords: P>
movss -20(%rbp), %xmm0
unpcklps %xmm0, %xmm0
cvtps2pd %xmm0, %xmm3
Merci pour la clarification!
Vous pouvez lancer de INT pour flotter en bouchent sur les éléments directement gcc, clang et icc générant une instruction https://godbolt.org/g/ku1apg p > p> cvtdq2ps xmm0, xmm0 code> pour cela . P>
Oui, c'est ce à quoi on dirait se produit - une conversion bitwise. (ou plutôt, pas de conversion du tout) afin que vous obteniez 4 flotteurs dénormalisés au lieu d'une conversion de valeur réelle.
C'est ce que les couts de vecteur sont définis à faire (tout ce qui serait complètement bonkers et ferait des idiomes de programmation vectorielle standard très douloureux à écrire). Si vous voulez réellement obtenir une conversion, vous voudrez probablement utiliser un intrinsèque d'une sorte, comme
_mm_cvtepi32_ps code> (ceci brise la belle indépendance architecturale de votre code de vecteur, bien sûr, qui est également ennuyeux. ; une approche commune consiste à utiliser un en-tête de traduction qui définit un ensemble portable de "intrinsics").
Je peux voir votre point, mais la question devient: quand cela casser i> serait utile?
@Cyrus le croit ou non, j'utilise réellement cela (bitwise) coulé plus souvent qu'une valeur de la valeur.
@Stephencanon Si vous voulez transformer ce commentaire dans une réponse, je serai heureux de l'accepter.
@Stephencanon j'ai essayé _mm_cvtepi32_ps, mais il n'est pas autorisé à moins que les conversions vectorielles, mais cette option ne doit pas être utilisée pour le nouveau code. Que faire à la place?
@ user877329 Vous avez besoin d'une distribution et de l'intrinsèque sur la machine GCC plus récente (il s'agit de Bonehed of the GCC Devs, mais c'est ce qu'il est):
_mm_cvtepi32_ps ((__ m128i) x) code>