Esta es la primera vez que trabajo con intrínsecamente SSE. Estoy tratando de convertir un simple fragmento de código en una versión más rápida usando Intel SSE intrínseco (hasta SSE4.2). Parece que me encuentro con una serie de errores.Optimización del código utilizando los intrínsecos de Intel SSE para la vectorización
La versión escalar del código es: (multiplicación matriz simple)
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;
}
}
Ésta es mi versión: He incluido # 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);
}
}
dónde voy mal con esto? Estoy recibiendo varios errores como este:
mm_vec.c (84): error: un valor de tipo "int" no se puede asignar a una entidad de tipo "__m128d" a_i = __mm_load_ps (& A [n * i + k]);
Esta es la forma en que estoy recopilando: ICC -O2 mm_vec.c -o vec
por favor alguien puede ayudar a convertir este código con precisión. ¡Gracias!
ACTUALIZACIÓN:
De acuerdo a sus sugerencias, que han realizado los siguientes cambios:
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);
}
}
Pero ahora parecen estar recibiendo un fallo de segmentación. Sé esto quizás porque no estoy accediendo correctamente a los subíndices de la matriz para la matriz A, B, C. Soy muy nuevo en esto y no estoy seguro de cómo proceder con esto.
Por favor, ayúdenme a determinar el enfoque correcto para manejar este código.
Estoy trabajando con icc not gcc. ¿Cree que manejarlo así: a_i = _mm_load_ps (& A [n * i + k]); ¿es el enfoque correcto? Los ejemplos que veo publicados en otra parte (incluso en la documentación Intel Intrinsic) tienen ejemplos muy básicos. las matrices A, B, C han sido todas asignadas con malloc. – PGOnTheGo
@Hello_PG La carga en sí no está directamente mal. No es necesario cargar c_i sin embargo. En su mayor parte ICC tiene las mismas extensiones que gcc; creo que ese es el caso para la alineación, aunque estoy más familiarizado con GCC que con ICC personalmente, así que lo califiqué con eso y me vinculé con los documentos que sabía cómo encontrar. malloc no garantiza una alineación adecuada en todas las plataformas, por lo que probablemente se necesite posix_memalign. ¿Falló la afirmación que sugerí? – Flexo
Cuando intento asignar memoria para A como esta: A = (float *) _ aligned_malloc (dimension * dimension * sizeof (float), 16); Obtengo un error de compilación: referencia indefinida a 'aligned_malloc 'con icc. así es como estoy compilando: icc -O2 mm_vec.c -o vec2 – PGOnTheGo