C で SSE 組み込み関数のロープを学習しようとしています。 double データの 2 成分ベクトルをロードし、それに何かを追加してからメモリに保存しようとするコードがあります。すべてが機能します。データを SEE レジスタにロードし、それらの SSE レジスタでデータを操作できますが、その処理されたデータを元の配列に書き戻そうとするとすぐに元の配列 (最初にデータを読み取った場所) に書き戻します。 place!) セグメンテーション違反が発生します。
誰でもこの問題について私にアドバイスしてもらえますか - これは私を狂わせています。
double res[2] __attribute__((aligned(16)));
for(int k=0; k<n; k++){
int i=0;
for(; i+1<n; i+=2)
{
__m128d cik = _mm_load_pd(&C[i+k*n]);
int j = 0;
for(; j+1<n; j+=2)
{
__m128d aTij = _mm_load_pd(&A_T[j+i*n]);
__m128d bjk = _mm_load_pd(&B[j+k*n]);
__m128d dotpr = _mm_dp_pd(aTij, bjk,2);
cik = _mm_add_pd(cik, dotpr);
}
_mm_store_pd(res, cik);
//C[i+k*n] = res[0];
}
}
上で述べたように、最初にデータを読み取った 1 次元配列 "C" に結果を格納する場所を除いて、このコードではすべてが機能します。つまり、前のコメント記号を削除すると、
//C[i+k*n] = res[0];
セグメンテーション違反が発生します。
アライメントされたメモリ バージョンの _mm_load_pd (したがって、C はメモリ内でアライメントされている必要があります) を使用して C から読み取ることができますが、書き戻すことはできません。「C」は整列する必要があり、ご覧のとおり「res」も整列する必要があります。
免責事項:私の元のコードを読んだ
_mm_store_pd(&C[i+k*n], cik);
これもセグメンテーション違反を引き起こし、問題を解決するために明示的な配置で「res」を導入し始めました。
補遺
A、B、C は次のように宣言されます。
buf = (double*) malloc (3 * nmax * nmax * sizeof(double));
double* A = buf + 0;
double* B = A + nmax*nmax;
double* C = B + nmax*nmax;
posix_memalign で試みられた解決策
元の 1 次元配列に書き込むときのセグメンテーション違反の問題を解決するために、対応する行列にバッファーを使用するようになりました。ただし、C_buff に書き戻そうとすると、これでも segfaul が発生します。
double res[2] __attribute__((aligned(16)));
double * A_T;
posix_memalign((void**)&A_T, 16, n*n*sizeof(double));
double * B_buff;
posix_memalign((void**)&B_buff, 16, n*n*sizeof(double));
double * C_buff;
posix_memalign((void**)&C_buff, 16, n*n*sizeof(double));
for(int y=0; y<n; y++)
for(int x=0; x<n; x++)
A_T[x+y*n] = A[y+x*n];
for(int x=0; x<n; x++)
for(int y=0; y<n; y++)
B_buff[y+x*n] = B[y+x*n];
for(int x=0; x<n; x++)
for(int y=0; y<n; y++)
C_buff[y+x*n] = C[y+x*n];
for(int k=0; k<n; k++){
int i=0;
for(; i+1<n; i+=2)
{
__m128d cik = _mm_load_pd(&C_buff[i+k*n]);
int j = 0;
for(; j+1<n; j+=2)
{
__m128d aTij = _mm_load_pd(&A_T[j+i*n]);
__m128d bjk = _mm_load_pd(&B_buff[j+k*n]);
__m128d dotpr = _mm_dp_pd(aTij, bjk,2);
cik = _mm_add_pd(cik, dotpr);
}
_mm_store_pd(&C_buff[i+k*n], cik);
//_mm_store_pd(res, cik);
//C_buff[i+k*n] = res[0];
//C_buff[i+1+k*n] = res[1];
}
}