我正在尝试学习 C 中 SSE 内在函数的原理。我有一段代码,我在其中加载双数据的双分量向量,向其中添加一些内容,然后尝试将其存储回内存。一切正常:我可以将我的数据加载到 SEE 寄存器中,我可以对这些 SSE 寄存器中的数据进行操作,但是当我尝试将处理过的数据写回原始数组时(这是我第一次读取数据的地方地方!)我得到一个分段错误。
任何人都可以就这个问题给我建议 - 这让我发疯。
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];
}
}
正如我上面所说的,除了我将结果存储回那个一维数组“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 尝试的解决方案
为了解决写入原始一维数组时的分段错误问题,我现在为相应的矩阵使用缓冲区。但是,在尝试写回 C_buff 时,这仍然会出现段错误!
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];
}
}