Vectorisation SSE de la fonction mathématique ‘pow’ gcc

J’essayais de vectoriser une boucle contenant l’utilisation de la fonction “pow” dans la bibliothèque mathématique. Je suis conscient que le compilateur Intel supporte l’utilisation de ‘pow’ pour les instructions sse – mais je n’arrive pas à le faire tourner avec gcc (je pense). C’est le cas avec lequel je travaille:

int main(){ int i=0; float a[256], b[256]; float x= 2.3; for (i =0 ; i<256; i++){ a[i]=1.5; } for (i=0; i<256; i++){ b[i]=pow(a[i],x); } for (i=0; i<256; i++){ b[i]=a[i]*a[i]; } return 0; } 

Je comstack avec ce qui suit:

 gcc -O3 -Wall -ftree-vectorize -msse2 -ftree-vectorizer-verbose=5 code.c -o runthis 

Ceci est sous OS X 10.5.8 avec la version 4.2 de gcc (j’ai aussi utilisé la version 4.5 et je ne pouvais pas dire si elle avait vectorisé quoi que ce soit – car elle ne produisait rien du tout). Il semble qu’aucune des boucles ne vectorise – existe-t-il un problème d’alignement ou un autre problème que je devrais utiliser restreindre? Si j’écris une des boucles en tant que fonction, le résultat (code) est légèrement plus détaillé:

 void pow2(float *a, float * b, int n) { int i; for (i=0; i<n; i++){ b[i]=a[i]*a[i]; } } 

sortie (sortie verbeuse de niveau 7):

 note: not vectorized: can't determine dependence between *D.2878_13 and *D.2877_8 bad data dependence. 

J’ai jeté un œil à la page d’ auto-vectorisation gcc, mais cela n’a pas aidé. S’il n’est pas possible d’utiliser pow dans la version gcc, où puis-je trouver la ressource pour effectuer une fonction pow-équivalente (je traite principalement de puissances entières).

Modifiez donc si je creusais dans une autre source, comment a-t-elle vectorisé cela?!:

 void array_op(double * d,int len,double value,void (*f)(double*,double*) ) { for ( int i = 0; i < len; i++ ){ f(&d[i],&value); } }; 

La sortie gcc pertinente:

 note: Profitability threshold is 3 loop iterations. note: LOOP VECTORIZED. 

Bien, maintenant je suis perdue – ‘d’ et ‘valeur’ ​​sont modifiés par une fonction que gcc ne connaît pas – étrange? J’ai peut-être besoin de tester cette partie un peu plus en profondeur pour m’assurer que les résultats sont corrects pour la partie vectorisée. Vous recherchez toujours une bibliothèque mathématique vectorisée – pourquoi n’y en a-t-il pas?

Utiliser __ressortingct ou consumr des entrées (assigner à des vars locaux) avant d’écrire des sorties devrait aider.

Dans l’état actuel des choses, le compilateur ne peut pas vectoriser car a peut alias b , donc multiplier 4 en parallèle et écrire 4 valeurs peut ne pas être correct.

(Notez que __ressortingct ne garantit pas la vectorisation du compilateur, mais on peut en dire autant qu’à l’heure actuelle, il ne le peut certainement pas ).

Ce n’est pas vraiment une réponse à votre question. mais plutôt une suggestion sur la façon dont on pourrait peut-être complètement éviter ce problème.

Vous mentionnez que vous êtes sur OS X; il existe déjà des API sur cette plate-forme qui fournissent les opérations que vous envisagez, sans nécessiter d’auto-vectorisation. Y a-t-il une raison pour laquelle vous ne les utilisez pas à la place? La vectorisation automatique est vraiment cool, mais elle nécessite un peu de travail et ne produit généralement pas des résultats aussi bons que ceux utilisant des API déjà vectorisées pour vous.

 #include  #include  int main() { int n = 256; float a[256], b[256]; // You can initialize the elements of a vector to a set value using memset_pattern: float threehalves = 1.5f; memset_pattern4(a, &threehalves, 4*n); // Since you have a fixed exponent for all of the base values, we will use // the vImage gamma functions. If you wanted to have different exponents // for each input (ie from an array of exponents), you would use the vForce // vvpowf( ) function instead (also part of Accelerate). // // If you don't need full accuracy, replace kvImageGamma_UseGammaValue with // kvImageGamma_UseGammaValue_half_precision to get better performance. GammaFunction func = vImageCreateGammaFunction(2.3f, kvImageGamma_UseGammaValue, 0); vImage_Buffer src = { .data = a, .height = 1, .width = n, .rowBytes = 4*n }; vImage_Buffer dst = { .data = b, .height = 1, .width = n, .rowBytes = 4*n }; vImageGamma_PlanarF(&src, &dst, func, 0); vImageDestroyGammaFunction(func); // To simply square a instead, use the vDSP_vsq function. vDSP_vsq(a, 1, b, 1, n); return 0; } 

Plus généralement, à moins que votre algorithme ne soit assez simple, la vectorisation automatique ne donnera probablement pas d’excellents résultats. D’après mon expérience, le spectre des techniques de vectorisation ressemble généralement à ceci:

 better performance worse performance more effort less effort +------+------+----------------------+----------------------------+-----------+ | | | | | | | | use vectorized APIs | auto vectorization | | skilled vector C | scalar code hand written assembly unskilled vector C