Optimisation du code SCC GCC

Ce post est étroitement liée à un autre que j'ai posté il y a quelques jours. Cette fois, j'ai écrit un code simple qui ajoute simplement une paire de matrices d'éléments, multiplie le résultat par les valeurs dans un autre tableau et les stocke dans une suite de tableau, toutes les variables à virgule flottante double précision tapé.

J'ai fait deux versions du même code: l'une avec le jeu d'instructions SSE, au moyen d'appels et un autre sans eux j'ai ensuite compilé avec gcc et-O0 niveau d'optimisation. Je les écris ci-dessous:

//SSE VERSION

#define N 10000
#define NTIMES 100000
#include <time.h>
#include <stdio.h>
#include <xmmintrin.h>
#include <pmmintrin.h>

double a[N] __attribute__((aligned(16)));
double b[N] __attribute__((aligned(16)));
double c[N] __attribute__((aligned(16)));
double r[N] __attribute__((aligned(16)));

int main(void){
  int i, times;
  for( times = 0; times < NTIMES; times++ ){
     for( i = 0; i <N; i+= 2){ 
        __m128d mm_a = _mm_load_pd( &a[i] );  
        _mm_prefetch( &a[i+4], _MM_HINT_T0 );
        __m128d mm_b = _mm_load_pd( &b[i] );  
        _mm_prefetch( &b[i+4] , _MM_HINT_T0 );
        __m128d mm_c = _mm_load_pd( &c[i] );
        _mm_prefetch( &c[i+4] , _MM_HINT_T0 );
        __m128d mm_r;
        mm_r = _mm_add_pd( mm_a, mm_b );
        mm_a = _mm_mul_pd( mm_r , mm_c );
        _mm_store_pd( &r[i], mm_a );
      }   
   }
 }

//NO SSE VERSION
//same definitions as before
int main(void){
  int i, times;
   for( times = 0; times < NTIMES; times++ ){
     for( i = 0; i < N; i++ ){
      r[i] = (a[i]+b[i])*c[i];
    }   
  }
}

Lors de la compilation avec -O0, gcc fait usage de XMM/registres MMX et SSE intstructions, si ce n'est précisément compte tenu de l'-mno-ess (et d'autres). J'ai inspecté le code assembleur généré pour le deuxième code, et j'ai remarqué qu'il rend l'utilisation de movsdaddsd et mulsd instructions. Il rend l'utilisation des instructions SSE, mais seulement de ceux qui utilisent la partie la plus basse de l'registres, si je ne me trompe pas. Le code assembleur généré pour la première C code fait usage, comme prévu, de la décennie et mulpd instructions, mais une assez grande assemblée de code a été généré.

De toute façon, le premier code devrait obtenir un meilleur résultat, pour autant que je sais, de SIMD paradigme, car à chaque itération de deux valeurs de résultat sont calculés. Encore que, le deuxième code effectue quelque chose comme 25% plus rapide que le premier. J'ai aussi fait un test avec une seule des valeurs de précision et d'obtenir des résultats similaires. Quelle est la raison?

source d'informationauteur Genís