ci-dessous cela semble être intrinsèque, cependant, je ne connais pas les fonctions intrinsèques. Aidez-moi s'il vous plaît à convertir le code réel. Surtout, Testfunc () est plus ambigu pour moi. Je suppose que c'est aussi pour le produit DOT de deux vecteurs de flotteurs, mais les étiquettes Lrep et Lexit me font confondre. S'il vous plaît, déterminez clairement pour moi. Et les intrinsions sont disponibles pour le processeur mobile?
pA = A; for (k = 0; k < K; k++) { pC = C; for (i = 0; i < M; i++) { pA = A + i * K + k; pB = B + k * N; for (j = N / 32; j > 0; j--) { _asm { mov eax, pC; mov ebx, pA; mov ecx, pB; vmovups ymm0, ymmword ptr[eax]; vmovss xmm1, dword ptr[ebx]; vbroadcastss ymm4, xmm1; vmovups ymm2, ymmword ptr[ecx]; vfmadd231ps ymm0, ymm4, ymm2; vmovups ymmword ptr[eax], ymm0; } pC += 8; pB += 8; _asm { mov eax, pC; mov ebx, pA; mov ecx, pB; vmovups ymm0, ymmword ptr[eax]; vmovss xmm1, dword ptr[ebx]; vbroadcastss ymm4, xmm1; vmovups ymm2, ymmword ptr[ecx]; vfmadd231ps ymm0, ymm4, ymm2; vmovups ymmword ptr[eax], ymm0; } pC += 8; pB += 8; _asm { mov eax, pC; mov ebx, pA; mov ecx, pB; vmovups ymm0, ymmword ptr[eax]; vmovss xmm1, dword ptr[ebx]; vbroadcastss ymm4, xmm1; vmovups ymm2, ymmword ptr[ecx]; vfmadd231ps ymm0, ymm4, ymm2; vmovups ymmword ptr[eax], ymm0; } pC += 8; pB += 8; _asm { mov eax, pC; mov ebx, pA; mov ecx, pB; vmovups ymm0, ymmword ptr[eax]; vmovss xmm1, dword ptr[ebx]; vbroadcastss ymm4, xmm1; vmovups ymm2, ymmword ptr[ecx]; vfmadd231ps ymm0, ymm4, ymm2; vmovups ymmword ptr[eax], ymm0; } pC += 8; pB += 8; } for (j = N / 32 * 32; j < N; j++) { *pC += *pA * *pB; pC += 1; pB += 1; } } }
3 Réponses :
Je ferai les premières lignes pour vous aider à démarrer, mais vraiment, si vous ne pouvez pas lire l'assemblage, vous devez vous référer au manuel de la CPU Intel pour pouvoir le déchiffrer.
mov esi, K8; sub esi, 8; shl esi, 2; xor edi, edi; mov edx, a; mov ebx, bb; mov esi, K8
Merci pour votre bonne réponse. Ensuite, qu'en est-il de "VXorps YMM3, YMM3, YMM3;"? Que devrais-je en apprendre davantage à ce sujet?
Même si je n'ai pas rencontré l'instruction VXorps avant que la recherche de Google rapide soit tout ce que je devais trouver la définition. Je suis aussi nouveau à ce jour, mais je suis presque sûr que l'idée n'est pas pour moi juste de tout répondre pour vous, mais plutôt de vous pousser dans la bonne direction. Corrige moi si je me trompe.
2 charges de vecteur (de la même position dans 2 tableaux) alimentant une FMA dans un accumulateur de vecteur sent un produit de point à moi. P>
Je n'ai pas vérifié le manuel de référence de l'ASM pour voir que l'opérande de destination était la somme plutôt que 1 des multiplicands, mais c'est comme ça qui a du sens. P>
La boucle triple imbriquée ressemble à une multiplication de matrice. Il diffuse 1 entrée tout en faisant une charge de vecteur de l'autre pour nourrir une FMA, il est donc probablement probablement générant un vecteur de résultats de SIMD pour une ligne de sortie. P>
Utilisation de la syntaxe ASM en ligne MSVC pour cela est plutôt mauvaise; Il ne peut accepter que des entrées via des opérandes de mémoire afin qu'il force une recharge + stocke entre chaque bloc d'ASM. Si vous allez dérouler, utilisez une grande instruction ASM et utilisez des déplacements dans les modes d'adressage. P>
idk pourquoi la boucle de produit de points est écrite inefficace (avec une branche conditionnelle et inconditionnelle à l'intérieur de la boucle), et non déroulée avec plusieurs accumulateurs. Vaincre à peu près le but de codage de la main dans l'ASM. Voir Pourquoi les mults ne prend que 3 cycles sur HASWELL, différents des tableaux d'instructions d'Agner? pour utiliser plusieurs accumulateurs pour masquer la latence FMA. Ou laissez CLang le faire pour vous quand vous déroulera + vectorisant une boucle C pure C. p>
Je ne sais pas non plus pourquoi il ne suit pas le résultat horizontal, mais il suffit plutôt de le stocker à la mémoire avec Quoi qu'il en soit, vous pouvez évidemment écrire un produit de point dans le code scalaire C, peut-être utiliser ou copiez la vectorisation manuelle avec intrinsique comme vmovups [c], ymm3 code>. Semble inutile. Je suppose que l'appelant doit recroouger à partir de la mémoire et de la somme, ou vous pouvez déclarer la fonction comme retournant un
__ m256 code> vecteur et ignorez le magasin. P>
FMA (A [i], B [i], somme) code> de Math.h pour reproduire le comportement de l'ASM de ne pas arrondir le résultat temporaire. P>
somme = _mm256_fmadd_ps (_mm256_loadu_ps (a [i]), _mm256_loadu_ps (b [i]), somme); code> ou quelque chose. (Voir Guide intrinsique d'Intel ). P>
dans intrinsique, c'est ce code répété 4 fois.
{ // vmovups ymm0, ymmword ptr[eax]; __m256 tempC = _mm256_loadu_ps((float*)pC); // vmovss xmm1, dword ptr[ebx]; // vbroadcastss ymm4, xmm1; __m256 tempA = _mm256_set1_ps(*pA); // vmovups ymm2, ymmword ptr[ecx]; __m256 tempB = _mm256_loadu_ps((float*)pB); // vfmadd231ps ymm0, ymm4, ymm2; __m256 result = _mm256_fmadd_ps(tempA, tempB, tempC); // vmovups ymmword ptr[eax], ymm0; _mm256_storeu_ps(pC, result); } pC += 8; pB += 8;
Merci pour votre bonne réponse. Pourriez-vous recommander des documents pour apprendre des intrinsions?
@Seyon pas vraiment. C'est le genre de chose où les ressources deviennent rapidement obsolètes. Je viens d'utiliser le guide Intel intrinsics: logiciel.intel.com/sites/landingpage/intrinsicsguide/... et gueule (avec les drapeaux -mavx2-----mfma -O2 et -ffast-maths).
@robthebloke et futurs lecteurs: préférez -march = haswell code> ou
-march = znver1 code> sur
-mavx2 -mfma code>. Surtout avec GCC, réglage
-MTUNE = CODE> à un processeur Intel avec AVX2 + FMA Règles SÉDUCTION
LOADU code> /
Stoin code> dans plusieurs instructions ASM. Pourquoi GCC ne résolve pas _mm256_loadu_pd comme un seul vmovupd? si vos données sont réellement alignées au moment de l'exécution, c'est un inconvénient éventuellement.
Un avantage d'utiliser intrinsique au lieu de l'ASM est que le compilateur peut hisser la diffusion de la boucle. (Au moins si vous utilisez float * restreindre PC code> ou
pa code> de sorte que le compilateur sait que les stocks via
pc code> n'affectent pas les valeurs lues de
PA CODE>.) Et oui, je pensais que quelque chose semblait étrange de ce matmul ASM quand j'écrivais ma réponse, mais je ne pouvais pas mettre mon doigt dessus. Les charges redondantes expliquent pourquoi une écluse rapide ne l'a pas empêchée de savoir s'il s'agissait d'une colonne ou d'une rangée. Bien repéré.
Vous pouvez directement copier le code de montage dans un bloc
__ asm code>. Cependant, votre architecture de projet devrait être X86, car X64 n'est pas prise en charge.
Salut, seccpur. Merci pour votre réponse. J'ai déjà copié le code de montage dans mon code. Mes problèmes ne consistent pas à ne pas travailler le code de montage mais ne peuvent pas déboguer correctement ce code de montage en ligne. VS 2015 Le débogueur saute ces lignes ASM, il fait donc une ligne incorrecte.