2011-11-27 8 views
7

mio tentativo iniziale si presentava (supposti vogliamo moltiplicare)Come si esegue il funzionamento a matrice 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)); 
} 

Ma questo chiaramente non funziona. Come approccio a questo?

dovrei caricare 4 alla volta ....

L'altra domanda è: se il mio array è molto grande (diciamo n = 1000), come posso farlo 16 byte allineati? È possibile?

+0

Quale risultato ti aspetti? Non vedo alcuna matrice, solo una moltiplicazione vettoriale. Inoltre, da dove vengono 3, 8 e 4? – pezcode

+0

@ user963889, le dimensioni non hanno alcun senso. Cosa stai cercando di fare? Moltiplicare un vettore 8x1, o una matrice di vettori, con una matrice 8x8? –

+0

@BrettHale Supponiamo di avere 8x8 multipli di un vettore 8x1. Voglio ottenere 8x1 come risultato. Sono bloccato. Ragazzi, potete guidarmi nella giusta direzione? Grazie. – user1012451

risposta

4

OK ... Utilizzerò una convenzione matrice a riga maggiore. Ogni riga di [m] richiede (2) elementi __m128 per ottenere 8 galleggianti. Il vettore 8x1 v è un vettore di colonna. Dato che stai usando l'istruzione haddps, suppongo che SSE3 sia disponibile. Trovare 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); 
} 

quanto per l'allineamento, una variabile di tipo __m128 opportuno allineare automaticamente in pila. Con la memoria dinamica, questa non è un'ipotesi sicura. Alcune malloc/nuove implementazioni possono restituire solo la memoria garantita per essere allineata a 8 byte.

L'intestazione intrinseca fornisce _mm_malloc e _mm_free. Il parametro align dovrebbe essere (16) in questo caso.

+0

Grazie. Il mio codice ora è simile al tuo dopo 2 giorni di lavoro ... ma il tuo è molto chiaro. Ho studiato. Grazie. – user1012451