Po raz pierwszy pracuję z wewnętrzną implementacją SSE. Próbuję przekonwertować prosty fragment kodu na szybszą wersję, używając Intel SSE intrinsic (upto SSE4.2). Wydaje mi się, że napotykam wiele błędów.Optymalizowanie kodu za pomocą Intel® Intel SSE do wektoryzacji
Skalar wersja kodu jest: (proste mnożenie macierzy)
void mm(int n, double *A, double *B, double *C)
{
int i,j,k;
double tmp;
for(i = 0; i < n; i++)
for(j = 0; j < n; j++) {
tmp = 0.0;
for(k = 0; k < n; k++)
tmp += A[n*i+k] *
B[n*k+j];
C[n*i+j] = tmp;
}
}
To jest moja wersja: Mam włączone #include
void mm_sse(int n, double *A, double *B, double *C)
{
int i,j,k;
double tmp;
__m128d a_i, b_i, c_i;
for(i = 0; i < n; i++)
for(j = 0; j < n; j++) {
tmp = 0.0;
for(k = 0; k < n; k+=4)
a_i = __mm_load_ps(&A[n*i+k]);
b_i = __mm_load_ps(&B[n*k+j]);
c_i = __mm_load_ps(&C[n*i+j]);
__m128d tmp1 = __mm_mul_ps(a_i,b_i);
__m128d tmp2 = __mm_hadd_ps(tmp1,tmp1);
__m128d tmp3 = __mm_add_ps(tmp2,tmp3);
__mm_store_ps(&C[n*i+j], tmp3);
}
}
Gdzie ja mam nie tak z tym? Dostaję kilka błędów tak:
mm_vec.c (84): error: wartość typu "int" nie może być przypisany do jednostki typu "__m128d" a_i = __mm_load_ps (& A [n * i + k]);
ten sposób jestem kompilacji: ICC -O2 mm_vec.c -o vec
Czy ktoś mógłby mi pomóc konwertowania ten kod dokładnie. Dzięki!
UPDATE:
Według swoimi sugestiami, dokonaniu następujących zmian:
void mm_sse(int n, float *A, float *B, float *C)
{
int i,j,k;
float tmp;
__m128 a_i, b_i, c_i;
for(i = 0; i < n; i++)
for(j = 0; j < n; j++) {
tmp = 0.0;
for(k = 0; k < n; k+=4)
a_i = _mm_load_ps(&A[n*i+k]);
b_i = _mm_load_ps(&B[n*k+j]);
c_i = _mm_load_ps(&C[n*i+j]);
__m128 tmp1 = _mm_mul_ps(a_i,b_i);
__m128 tmp2 = _mm_hadd_ps(tmp1,tmp1);
__m128 tmp3 = _mm_add_ps(tmp2,tmp3);
_mm_store_ps(&C[n*i+j], tmp3);
}
}
Ale teraz wydaje się być coraz usterki segmentacji. Wiem o tym, być może dlatego, że nie mam dostępu do tablic indeksów poprawnie dla tablic A, B, C. Jestem na to nowy i nie wiem, jak to zrobić.
Proszę pomóż mi określić prawidłowe podejście do obsługi tego kodu.
Pracuję z icc nie gcc. Czy uważasz, że obsługa tego w następujący sposób: a_i = _mm_load_ps (& A [n * i + k]), czy to właściwe podejście? Przykłady, które widzę gdzie indziej (nawet w dokumentacji Intrinsic Intela) mają bardzo proste przykłady. tablice A, B, C zostały przydzielone za pomocą malloc. – PGOnTheGo
@Hello_PG Ładunek nie jest bezpośrednio błędny. Nie musisz jednak ładować c_i. W przeważającej części ICC ma takie same rozszerzenia jak gcc - myślę, że tak jest w przypadku wyrównania, jestem bardziej zaznajomiony z GCC niż z ICC osobiście, więc zakwalifikowałem go i powiązałem z dokumentami, które umiałem znaleźć. malloc nie gwarantuje odpowiedniego dopasowania na wszystkich platformach, więc posix_memalign jest prawdopodobnie potrzebny. Czy twierdzenie, które zasugerowałem, zawiodło? – Flexo
Kiedy próbuję przydzielić pamięć dla A w ten sposób: A = (float *) _ aligned_malloc (wymiar * wymiar * sizeof (float), 16); Dostaję błąd kompilacji: niezdefiniowane odwołanie do "aligned_malloc" z icc. tak właśnie kompiluję: icc -O2 mm_vec.c -o vec2 – PGOnTheGo