2011-11-27 10 views
7

Mi intento inicial era la siguiente (se supone que queremos multiplicar)¿Cómo realizo la operación de matriz 8 x 8 usando SSE?

__m128 mat[n]; /* rows */ 
    __m128 vec[n] = {1,1,1,1}; 
    float outvector[n]; 
    for (int row=0;row<n;row++) { 
     for(int k =3; k < 8; k = k+ 4) 
     { 
      __m128 mrow = mat[k]; 
      __m128 v = vec[row]; 
      __m128 sum = _mm_mul_ps(mrow,v); 
      sum= _mm_hadd_ps(sum,sum); /* adds adjacent-two floats */ 
     } 
      _mm_store_ss(&outvector[row],_mm_hadd_ps(sum,sum)); 
} 

Pero esto claramente no funciona. ¿Cómo me acerco a esto?

que debería cargar 4 a la vez ....

La otra pregunta es: si mi matriz es muy grande (digamos n = 1000), ¿cómo puedo hacer que sea de 16 bytes alineados? ¿Es eso posible?

+0

¿Qué resultado espera? No veo ninguna matriz, solo una multiplicación vectorial. Además, ¿de dónde vienen 3, 8 y 4? – pezcode

+0

@ user963889, las dimensiones no tienen ningún sentido. ¿Que estás tratando de hacer? ¿Multiplicar un vector de 8x1 o una matriz de vectores por una matriz de 8x8? –

+0

@BrettHale Supongamos que tenemos múltiplos 8x8 un vector 8x1. Quiero obtener 8x1 como resultado. Estoy atascado. ¿Pueden ustedes guiarme en la dirección correcta? Gracias. – user1012451

Respuesta

4

OK ... Usaré una convención matricial de filas principales. Cada fila de [m] requiere (2) __m128 elementos para producir 8 flotadores. El vector 8x1 v es un vector de columna. Como está utilizando la instrucción haddps, supongo que SSE3 está disponible. Encontrar r = [m] * v:

void mul (__m128 r[2], const __m128 m[8][2], const __m128 v[2]) 
{ 
    __m128 t0, t1, t2, t3, r0, r1, r2, r3; 

    t0 = _mm_mul_ps(m[0][0], v[0]); 
    t1 = _mm_mul_ps(m[1][0], v[0]); 
    t2 = _mm_mul_ps(m[2][0], v[0]); 
    t3 = _mm_mul_ps(m[3][0], v[0]); 

    t0 = _mm_hadd_ps(t0, t1); 
    t2 = _mm_hadd_ps(t2, t3); 
    r0 = _mm_hadd_ps(t0, t2); 

    t0 = _mm_mul_ps(m[0][1], v[1]); 
    t1 = _mm_mul_ps(m[1][1], v[1]); 
    t2 = _mm_mul_ps(m[2][1], v[1]); 
    t3 = _mm_mul_ps(m[3][1], v[1]); 

    t0 = _mm_hadd_ps(t0, t1); 
    t2 = _mm_hadd_ps(t2, t3); 
    r1 = _mm_hadd_ps(t0, t2); 

    t0 = _mm_mul_ps(m[4][0], v[0]); 
    t1 = _mm_mul_ps(m[5][0], v[0]); 
    t2 = _mm_mul_ps(m[6][0], v[0]); 
    t3 = _mm_mul_ps(m[7][0], v[0]); 

    t0 = _mm_hadd_ps(t0, t1); 
    t2 = _mm_hadd_ps(t2, t3); 
    r2 = _mm_hadd_ps(t0, t2); 

    t0 = _mm_mul_ps(m[4][1], v[1]); 
    t1 = _mm_mul_ps(m[5][1], v[1]); 
    t2 = _mm_mul_ps(m[6][1], v[1]); 
    t3 = _mm_mul_ps(m[7][1], v[1]); 

    t0 = _mm_hadd_ps(t0, t1); 
    t2 = _mm_hadd_ps(t2, t3); 
    r3 = _mm_hadd_ps(t0, t2); 

    r[0] = _mm_add_ps(r0, r1); 
    r[1] = _mm_add_ps(r2, r3); 
} 

Como para la alineación, una variable de un __m128 tipo debe estar alineado automáticamente en la pila. Con la memoria dinámica, esta no es una suposición segura. Algunas implementaciones malloc/new solo pueden devolver memoria que garantiza que está alineada con 8 bytes.

El encabezado intrinsics proporciona _mm_malloc y _mm_free. El parámetro de alineación debe ser (16) en este caso.

+0

Gracias. Mi código es similar al tuyo ahora después de 2 días de trabajo ... pero el tuyo está muy claro. He aprendido. Gracias. – user1012451