2016-03-03 1 views
4

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 ...)

+0

Avez-vous essayé '-O0'? Ce qui se produit? – mindriot

+1

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

+0

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

Répondre

1

L'intrinsèque nécessite une valeur immédiate. La compilation ne fonctionne que parce qu'il a été optimisé comme une constante de la boucle par le déroulement et la compilation avec -O0 ne déclenche l'erreur suivante:

(...)\lib\gcc\x86_64-w64-mingw32\4.9.2\include\avxintrin.h:331: error: the last argument must be an 8-bit immediate

 __mask); 
      ^

Un cas similaire a été signalé avec icc ici:

https://software.intel.com/en-us/forums/intel-c-compiler/topic/287217