2011-11-27 6 views
7

私の最初の試みは、このように見えた(私たちは乗算したいはず)SSEを使用して8×8行列演算を実行するにはどうすればよいですか?

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

しかし、これは明らかに動作しません。私はこれにどのようにアプローチするのですか?

私は一度に4をロードする必要があります....

他の質問がある:私の配列は、(= Nたとえば1000)非常に大きい場合には、どのように私はそれの16バイトが整列することができますか?それも可能ですか?

+0

どのような結果が期待されますか?私は行列を見ません、ベクトル乗算だけです。また、3、8、4はどこから来たのですか? – pezcode

+0

@ user963889では、寸法が意味をなさない。あなたは何をしようとしているのですか? 8x1ベクトルまたはベクトルの配列に8x8行列を掛けますか? –

+0

@BrettHaleベクトル8x1の8x8の倍数を仮定します。私は結果として8x1を取得したい。ハマった。あなたは私を正しい方向に導くことができますか?ありがとう。 – user1012451

答えて

4

OK ...私は行の主要な行列の規則を使用します。 [m]の各行には、8個の浮動小数点を得るために(2)__m128要素が必要です。 8x1ベクトルvは列ベクトルです。 haddps命令を使用しているので、SSE3が利用可能であると仮定します。 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); 
} 

を、型__m128の変数は自動的にスタック上に整列されるべきです。ダイナミックメモリでは、これは安全な前提ではありません。一部のmalloc /新しい実装では、8バイト境界になるように保証されたメモリしか返されません。

intrinsicsヘッダーは_mm_mallocと_mm_freeを提供します。この場合、alignパラメータは(16)でなければなりません。

+0

ありがとうございます。私のコードは2日間の作業後にあなたのものに似ていますが、あなたのことははっきりしています。私は学んだ。ありがとう。 – user1012451

2

インテルは、1×1から6×6までのサイズのマトリックスについてSmall Matrix Libraryを開発しました。アプリケーションノートAP-930 Streaming SIMD Extensions - Matrix Multiplicationは、2つの6×6行列を掛けるためのアルゴリズムを詳細に説明している。これは、ある程度の努力を払って、他のサイズ行列に適応可能でなければならない。

関連する問題