2011-11-27 24 views
7

Benim ilk girişimi böyle görünüyordu (biz çarpmak istiyoruz sözde)SSE kullanarak 8 x 8 matris işlemini nasıl yapabilirim?

__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)); 
} 

Ama bu basit çalışmaz. Buna nasıl yaklaşırım? Bir defada 4 yüklenmesi gereken

....

diğer soru: benim dizi Ben hizalanmış o 16-bayt hale nasıl (n = 1000 diyelim) çok büyük değilse? Bu mümkün mü?

+0

Ne tür bir sonuç bekliyorsunuz? Herhangi bir matris görmüyorum, sadece bir vektör çarpımı. Ayrıca, 3, 8 ve 4 nereden geliyor? – pezcode

+0

@ user963889, boyutlar herhangi bir anlam ifade etmiyor. Ne yapmaya çalışıyorsun? 8x1 vektörü veya 8x8 matris ile vektör dizisini çoğaltın mı? –

+0

@BrettHale Farz edelim ki 8x8 katları bir vektör 8x1. Sonuç olarak 8x1 almak istiyorum. Sıkıştım. Beni doğru yöne yönlendirir misiniz? Teşekkürler. – user1012451

cevap

4

Tamam ... Sıralı bir matris kuralı kullanacağım. Her bir satır [m], (2) 8 şamandıra vermek için __m128 eleman gerektirir. 8x1 vektörü v bir kolon vektörüdür. haddps talimatını kullandığınızdan, SSE3'ün kullanılabileceğini varsayacağım. r = [m] * v bulma: hizalama için de

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); 
} 

, bir tür __m128 değişken bir otomatik yığın hizalanmalıdır. Dinamik hafıza ile bu güvenli bir varsayım değildir. Bazı malloc/yeni uygulamalar yalnızca 8 baytlık olarak garanti edilen belleği iade edebilir.

İçsel üstbilgi _mm_malloc ve _mm_free sağlar. Bu durumda align parametresi (16) olmalıdır.

+0

için bir cevap sağladı. Benim kodum 2 gün çalıştıktan sonra sana benziyor ... ama seninki çok açık. Öğrendim. Teşekkürler. – user1012451