Od pewnego czasu zmagam się z wektoryzacją konkretnej aplikacji i próbowałem wszystkiego. Od autovectorization, po ręcznie kodowane SSE. Ale jakoś nie jestem w stanie uzyskać przyspieszenia w mojej aplikacji opartej na szablonie.Nie można wykryć, dlaczego następujący fragment kodu nie był wektoryzowany
Poniżej znajduje się fragment mojego obecnego kodu, który wektoryzowałem za pomocą wewnętrznej samoistości SSE. Podczas kompilacji (Intel icc) przy użyciu -vec-report3 ciągle otrzymuję komunikat:
uwaga: pętla nie była wektoryzowana: instrukcja nie może być wektoryzowana.
#pragma ivdep
for (i = STENCIL; i < z - STENCIL; i+=4)
{
it = it2 + i;
__m128 tmp2i = _mm_mul_ps(_mm_add_ps(_mm_load_ps(&p2[i+j*it_j-it_j4+k*it_k]),_mm_load_ps(&p2[i+j*it_j+it_j4+k*it_k])),X4_i); //loop was not vectorized: statement cannot be vectorized
__m128 tmp3 = _mm_mul_ps(_mm_add_ps(_mm_load_ps(&p2[i+j*it_j-it_j3+k*it_k]),_mm_load_ps(&p2[i+j*it_j+it_j3+k*it_k])),X3_i);
__m128 tmp4 = _mm_mul_ps(_mm_add_ps(_mm_load_ps(&p2[i+j*it_j-it_j2+k*it_k]),_mm_load_ps(&p2[i+j*it_j+it_j2+k*it_k])),X2_i);
__m128 tmp5 = _mm_mul_ps(_mm_add_ps(_mm_load_ps(&p2[i+j*it_j-it_j +k*it_k]),_mm_load_ps(&p2[i+j*it_j+it_j +k*it_k])),X1_i);
__m128 tmp6 = _mm_add_ps(_mm_add_ps(_mm_add_ps(tmp2i,tmp3),_mm_add_ps(tmp4,tmp5)), _mm_mul_ps(_mm_load_ps(&p2[it]),C00_i));
_mm_store_ps(&tmp2[i],tmp6);
}
Am I czegoś brakuje kluczową? Ponieważ komunikat nie wyjaśnia, dlaczego nie można go wektoryzować, trudno mi stwierdzić wąskie gardło.
AKTUALIZACJA: Po dokładnym rozważeniu sugestii, zmodyfikowałem kod w następujący sposób. Pomyślałem, że najlepiej jest rozbić to jeszcze bardziej, aby zidentyfikować stwierdzenia, które faktycznie są odpowiedzialne za uzależnienie wektorowe.
//#pragma ivdep
for (i = STENCIL; i < z - STENCIL; i+=4)
{
it = it2 + i;
__m128 center = _mm_mul_ps(_mm_load_ps(&p2[it]),C00_i);
u_j4 = _mm_load_ps(&p2[i+j*it_j-it_j4+k*it_k]); //Line 180
u_j3 = _mm_load_ps(&p2[i+j*it_j-it_j3+k*it_k]);
u_j2 = _mm_load_ps(&p2[i+j*it_j-it_j2+k*it_k]);
u_j1 = _mm_load_ps(&p2[i+j*it_j-it_j +k*it_k]);
u_j8 = _mm_load_ps(&p2[i+j*it_j+it_j4+k*it_k]);
u_j7 = _mm_load_ps(&p2[i+j*it_j+it_j3+k*it_k]);
u_j6 = _mm_load_ps(&p2[i+j*it_j+it_j2+k*it_k]);
u_j5 = _mm_load_ps(&p2[i+j*it_j+it_j +k*it_k]);
__m128 tmp2i = _mm_mul_ps(_mm_add_ps(u_j4,u_j8),X4_i);
__m128 tmp3 = _mm_mul_ps(_mm_add_ps(u_j3,u_j7),X3_i);
__m128 tmp4 = _mm_mul_ps(_mm_add_ps(u_j2,u_j6),X2_i);
__m128 tmp5 = _mm_mul_ps(_mm_add_ps(u_j1,u_j5),X1_i);
__m128 tmp6 = _mm_add_ps(_mm_add_ps(tmp2i,tmp3),_mm_add_ps(tmp4,tmp5));
__m128 tmp7 = _mm_add_ps(tmp6,center);
_mm_store_ps(&tmp2[i],tmp7); //Line 196
}
Kiedy skompilować (ICC) powyższy kod bez #pragma ivdep
otrzymuję następujący komunikat:
remark: loop was not vectorized: existence of vector dependence.
vector dependence: assumed FLOW dependence between tmp2 line 196 and tmp2 line 196.
vector dependence: assumed ANTI dependence between tmp2 line 196 and tmp2 line 196.
Kiedy skompilować (ICC) to z #pragma ivdep
, pojawia się następujący komunikat:
remark: loop was not vectorized: unsupported data type. //Line 180
Dlaczego sugerowana jest zależność dla linii 196? Jak mogę wyeliminować sugerowaną zależność wektorową?
Uprość konstrukcje 'for' przez wstępne obliczenie wartości końcowej i liczby pętli. –
Nie można go wektoryzować, ponieważ już to wektoryzowałeś. Nie uzyskujesz żadnego przyspieszenia, ponieważ twój współczynnik obliczeń/dostępu do pamięci jest zbyt niski. – Mysticial
To nie jest wyrównanie, które było moją pierwszą myślą (naprawił mnie Mysticial), ale zdecydowanie warto zacząć od uproszczenia wyrażeń dla przesunięć tablicy. –