Evadream -jbd- | Bonjour tout le monde,
Je m'intéresse en ce moment, plus par curiosité que par réel besoin, à l'utilisation des instrinsics pour avoir un accès "aisé" aux capacités SIMD des processeurs. Ayant un AthlonXP, j'ai fais qqs essais afin d'exploiter les instructions SSE. J'ai analysé le code asm généré par le compilateur, et cela soulève plusieurs interrogation. (J'ai compilé en Os parce que si je compile en O3, le compilo court circuite les instructions de la boucle et ne fait le "calcul" qu'une seule fois) :
Voici le bout de code et sa "variante" qui vont nous intéresser :
Version de base
Code :
- /*
- * Compilation:
- *
- * asm > gcc -std=c99 -Os -msse -S -c sse.c
- * exe > gcc -std=c99 -Os -msse -c sse.c -o sse
- *
- */
- #include <stdio.h>
- #include <xmmintrin.h>
- float a[4] __attribute__((aligned(16))) = { 2.f, 3.f, 4.f, 5.f } ;
- float b[4] __attribute__((aligned(16))) = { 5.f, 6.f, 7.f, 8.f } ;
- float c[4] __attribute__((aligned(16))) ;
- int main(int argc, char* argv[])
- {
- for ( int i = 0 ; i < 100000 ; ++i ) {
- for ( int j = 0 ; j < 100000 ; ++j ) {
- _mm_store_ps(c,
- _mm_add_ps( _mm_load_ps(a) ,_mm_load_ps(b))) ;
- }
- }
- printf("%f %f %f %f\n", c[0], c[1], c[2], c[3]) ;
- }
|
Version de base - les lignes de code assembleur qui m'intéressent
Code :
- .L20:
- movaps a, %xmm0
- decl %eax
- movaps b, %xmm1
- addps %xmm1, %xmm0
- movaps %xmm0, c
- jns .L20
|
Version bis
Code :
- /*
- * Compilation:
- *
- * asm > gcc -std=c99 -Os -msse -S -c ssebis.c
- * exe > gcc -std=c99 -Os -msse -c ssebis.c -o ssebis
- *
- */
- #include <stdio.h>
- #include <xmmintrin.h>
- union sse4 {
- __m128 m ;
- float values[4] ;
- } a,b,c ;
- int main(int argc, char* argv[])
- {
- a.values[0] = 2.f ; a.values[1] = 3.f ; a.values[2] = 4.f ; a.values[3] = 5.f ;
- b.values[0] = 5.f ; b.values[1] = 6.f ; b.values[2] = 7.f ; b.values[3] = 8.f ;
- for ( int i = 0 ; i < 100000 ; ++i ) {
- for ( int j = 0 ; j < 100000 ; ++j ) {
- c.m = _mm_add_ps(a.m, b.m) ;
- }
- }
- printf("%f %f %f %f\n", c[0], c[1], c[2], c[3]) ;
- }
|
Version bis - les lignes de code assembleur qui m'intéressent
Code :
- .L17:
- movaps a, %xmm0
- decl %eax
- addps b, %xmm0
- movaps %xmm0, c
- jns .L17
|
Les performances pour les deux versions sont les mêmes en -Os, de même en -O3 en introduisant du travail dans la boucle (en changeant la valeur du vecteur a par exemple). (environ 10 secondes de "calculs" ).
N'ayant aucune expérience en assembleur, je me demande comment fonctionne l'instruction addps. D'après ce que j'ai compris (c'est là ou ca coince ), elle prend en paramètre 2 registres sse afin de mettre le résultat dans un des deux (ici, xmm0, syntaxe AT/T). Or ici, b est un emplacement mémoire arbitraire dans cette version bis. Comme le programme fonctionne, que dois-je en conclure ? Il y a un movaps "caché" ? Y'a t'il quelque chose à savoir ou quelque chose qui ne va pas dans mon analyse ?
Question subsidiaire : Je n'ai pas l'impression que l'on puisse décider du registre sse à utiliser via les intrinsics, vous confirmez ?
Merci d'avance pour vos réponses ! @++
Edit : Il est dangereux de poster ce genre de sujet à 4h30 du matin . Je verrais bien ce que ca donne demain ! Message édité par Evadream -jbd- le 19-11-2004 à 05:17:57
|