Optymalizacja - suma - łancuch zależności
Zadanie polega na obliczeniu sumy elementów tablicy tab o danym N (operację powtarzamy ITER razy)
Programie suma_dependancy.cpp zdefiniowano kilka sposobów liczenia sumy. Sposób wybieramy definiując odpowiednie makro.
SIMPLE
sum = 0.0;
for (int i = 0; i < N; i++)
sum += tab[i];
PREFETCH
- Cache’ujemy dane z odpowiednim wyprzedzeniem.
- Rozwijamy pętlę, tak aby w jednej iteracji wykorzystać cały wiersz cache.
- Powielając zmienne, unikamy długiego ciągu zależności (kilka dodawań może wykonać się w jednym cyklu zegara).
double sum1 = 0., sum2 = 0., sum3 = 0., sum4 = 0.;
for (int i = 0; i < N; i += 4){
sum1 += tab[i];
sum2 += tab[i+1];
sum3 += tab[i+2];
sum4 += tab[i+3];
__builtin_prefetch(tab+i+16, 0, 3); // (adres, rw (w=1), locality strength(1-3))
}
sum = (sum1 + sum2) + (sum3 + sum4);
VECTOR
__m256d result = {0.0,0.0,0.0,0.0};
for(int i=0; i<N; i+= 4){
__m256d x = _mm256_loadu_pd(tab+i);
result = _mm256_add_pd(result, x);
}
double z[4] = {0.};
_mm256_storeu_pd(z, result);
sum = z[0]+z[1]+z[2]+z[3];
Uzyskane czasy
Wersja | Małe | Duże | Duże |
---|---|---|---|
rozmiar N | 100 | 100000 | 100000 |
ITER | 150000000 | 15000 | 15000 |
optymalizacja | -O3 | -O3 | -O0 |
SIMPLE | 7.69224s | 1.37358s | 3.0922s |
PREFETCH | 2.59237s | 0.361434s | 1.27144s |
VECTOR | 1.95894s | 0.34297s | 1.44102s |
Uruchomienie
make run_dependancy