je dois faire les opérations suivantes: AVXLes boucles C++ peuvent-elles être garanties par le compilateur (gcc)?
__m256 perm, func;
__m256 in = _mm256_load_ps(inPtr+x);
__m256 acc = _mm256_setzero_ps();
perm = _mm256_shuffle_ps(in, in, _MM_SHUFFLE(3,2,1,0));
func = _mm256_load_ps(fPtr+0);
acc = _mm256_add_ps(acc, _mm256_mul_ps(perm, func));
perm = _mm256_shuffle_ps(in, in, _MM_SHUFFLE(2,3,0,1));
func = _mm256_load_ps(fPtr+1);
acc = _mm256_add_ps(acc, _mm256_mul_ps(perm, func));
perm = _mm256_shuffle_ps(in, in, _MM_SHUFFLE(1,0,3,2));
func = _mm256_load_ps(fPtr+2);
acc = _mm256_add_ps(acc, _mm256_mul_ps(perm, func));
perm = _mm256_shuffle_ps(in, in, _MM_SHUFFLE(0,1,2,3));
func = _mm256_load_ps(fPtr+3);
acc = _mm256_add_ps(acc, _mm256_mul_ps(perm, func));
Cela pourrait être réécrite comme ceci:
__m256 perm, func;
__m256 in = _mm256_load_ps(inPtr+x);
__m256 acc = _mm256_setzero_ps();
for(int i=0;i<4;++i)
{
perm = _mm256_shuffle_ps(in, in, _MM_SHUFFLE(3^i,2^i,1^i,0^i));
func = _mm256_load_ps(fPtr+i);
acc = _mm256_add_ps(acc, _mm256_mul_ps(perm, func));
}
Cette compile en gcc 4.9.1, en dépit _mm256_shuffle_ps
accepter seulement des valeurs entières immédiates comme troisième paramètre . Cela signifie que i
est accepté comme immédiat, ce qui signifie que la boucle a été déroulée. Donc je suis curieux: est-ce que c'est quelque chose de garanti par le compilateur, ou est-ce que cela pourrait causer des erreurs de compilation quand les drapeaux d'opimisation sont modifiés, ou quand la version de gcc change? Qu'en est-il de l'utilisation d'autres compilateurs (msvc, icc, clang ...)
Avez-vous essayé '-O0'? Ce qui se produit? – mindriot
Aussi, comment arrivez-vous à la conclusion que seul un immédiat est pris en charge? La [mise en œuvre du CCG] (https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/config/i386/avxintrin.h;hb=HEAD#l331) semble prendre un 'const int', et [la spécification Intel] (https://software.intel.com/en-us/node/583079) semble indiquer la même chose. – mindriot
La signature 'const int' ne dit rien, car il n'y a rien dans le langage qui spécifie si un paramètre est un immédiat. De plus, tout paramètre 'imm' dans la documentation intrinsèque d'intel est immédiat. Cela est plus clair dans la documentation MSDN. Et enfin, l'utilisation d'une valeur non immédiate dans gcc déclenche l'erreur: "Le dernier argument doit être un 8-bit immédiat" – galinette