2017-12-06 6 views
0
int MAX_DIM = 100; 
    float a[MAX_DIM][MAX_DIM]__attribute__ ((aligned(16))); 
    float b[MAX_DIM][MAX_DIM]__attribute__ ((aligned(16))); 
    float d[MAX_DIM][MAX_DIM]__attribute__ ((aligned(16))); 
    /* 
    * I fill these arrays with some values 
    */ 

for(int i=0;i<MAX_DIM;i+=1){ 

     for(int j=0;j<MAX_DIM;j+=4){ 

     for(int k=0;k<MAX_DIM;k+=4){ 

      __m128 result = _mm_load_ps(&d[i][j]); 

      __m128 a_line = _mm_load_ps(&a[i][k]); 

      __m128 b_line0 = _mm_load_ps(&b[k][j+0]); 

      __m128 b_line1 = _mm_loadu_ps(&b[k][j+1]); 

      __m128 b_line2 = _mm_loadu_ps(&b[k][j+2]); 

      __m128 b_line3 = _mm_loadu_ps(&b[k][j+3]); 

     result = _mm_add_ps(result, _mm_mul_ps(_mm_shuffle_ps(a_line, a_line, 0x00), b_line0)); 
     result = _mm_add_ps(result, _mm_mul_ps(_mm_shuffle_ps(a_line, a_line, 0x55), b_line1)); 
     result = _mm_add_ps(result, _mm_mul_ps(_mm_shuffle_ps(a_line, a_line, 0xaa), b_line2)); 
     result = _mm_add_ps(result, _mm_mul_ps(_mm_shuffle_ps(a_line, a_line, 0xff), b_line3)); 
     _mm_store_ps(&d[i][j],result); 
     } 
     } 
    } 

上記のコードは、SSEを使用して行列乗算を行うために作成したものです。コードはフローとして実行されます。行から4つの要素を取り出し、bの列から4つの要素を乗算し、列の次の4つの要素に移動します。SSE組み込み関数を使用したサイズ100 * 100の行列乗算

エラーが発生します

が、私はUbuntuの上でGCC 5.4.0を使用する理由Segmentation fault (core dumped)私は本当に知らない16.04.5

編集: セグメンテーションフォールトが_mm_loadu_ps によって解決された。また、私がもしgreatfullなり、論理と間違って何かがあります誰かが私を見つけるのを助ける

+0

LinuxでGCCを使用しているようです。 a)OS、b)コンパイラとバージョン、c)gdb(該当する場合)で実行し、スタックトレースをコピー/ペーストします。 – paulsm4

+2

いくつかのロード(最後の3行)の位置がずれています - これらの(またはすべての)ロードに '_mm_loadu_ps 'を使用してください。 –

答えて

2

セグメンテーションフォールトが_mm_loadu_psにより解決した。また、ロジックに問題がある...

あなたはb[k][j+0..7]で4つのオーバーラップウィンドウをロードしています。 (これがあなたがloaduを必要とした理由です)。

はおそらく、あなたはb[k][j+0]+4+8+12をロードするためのもの?その場合は、bを64に合わせる必要があります。そのため、4つのロードはすべて同じキャッシュラインから実行されます(パフォーマンス用)。ストライドされたアクセスは素晴らしいことではありませんが、タッチするすべてのキャッシュラインのすべての64バイトを使用する方が、行の長さと列の長さをブロッキングのないスカラーコードで完全に間違えるほど良くなります。

は、私はあなたのテキスト記述があなたのコードを記述わからないb

から列から4つの要素を掛けaから行から4つの要素を取ります。

bを既に転記していない限り、メモリ内で連続していないため、同じ列の複数の値をSIMDロードでロードすることはできません。

多次元配列は「行の長さ」です。最後のインデックスは、次の上位メモリアドレスに移動するときに最も速く変化するインデックスです。 _mm_loadu_ps(&b[k][j+1])はあなたにb[k+0..3][j+1]を与えるつもりだったと思いましたか?もしそうなら、これはSSE matrix-matrix multiplicationの複製である(その質問は、32ビット整数ではなく、32ビット浮動小数点、同じレイアウトの問題を使用している。ワーキングループ構造のためにそれを参照してください。)


これをデバッグするには、値の簡単なパターンをb[]に入れてください。同様に

#include <stdalign.> 

alignas(64) float b[MAX_DIM][MAX_DIM] = { 
    0000, 0001, 0002, 0003, 0004, ..., 
    0100, 0101, 0102, ..., 
    0200, 0201, 0202, ..., 
}; 

// i.e. for (...) b[i][j] = 100 * i + j; 

デバッガでコードをステップ実行すると、どのような値がベクトルになるのかが分かります。あなたのa[][]値について

、あなたが(代わりにC変数の)レジスタで探しているなら、多分そう90000.0 + 100 * i + jを使用あなたはまだaであり、どのbである値を伝えることができます。


関連:

関連する問題