我想计算k=0
到k=100
A[j][k]=((A[j][k]-con*A[r][k])%2);
为此我将(con*A[r][k])
存储在某些int temp[5]
中
然后在SIMD中A[j][k]-temp[]
执行错误的代码下面的代码行__m128i m5=_mm_sub_epi32(*m3,*m4);
while((k+4)<100)
{
__m128i *m3 = (__m128i*)A[j+k];
temp[0]=con*A[r][k];
temp[1]=con*A[r][k+1];
temp[2]=con*A[r][k+2];
temp[3]=con*A[r][k+3];
__m128i *m4 = (__m128i*)temp;
__m128i m5 =_mm_sub_epi32(*m3,*m4);
(temp_ptr)=(int*)&m5;
printf("%ld,%d,%ld\n",A[j][k],con,A[r][k]);
A[j][k] =temp_ptr[0]%2;
A[j][k+1]=temp_ptr[1]%2;
A[j][k+2]=temp_ptr[2]%2;
A[j][k+3]=temp_ptr[3]%2;
k=k+4;
}
答案 0 :(得分:2)
最有可能的是,你没有注意对齐。 SIMD指令需要16字节对齐(参见this文章)。否则,您的程序将崩溃。
对齐,或者某处有错误的索引,并且访问错误的内存。
答案 1 :(得分:1)
如果没有j,k和r的可能值,很难说明原因,但很可能是你的一个数组过度索引
答案 2 :(得分:0)
如果您想实施:
for (k = 0; k < 100; k += 4)
{
A[j][k] = (A[j][k] - con * A[r][k]) % 2;
}
并且您希望看到SIMD的一些好处,那么您需要在SIMD中完成所有操作,即不要混用SIMD和标量代码。
例如(未经测试):
const __m128i vcon = _mm_set1_epi32(con);
const __m128i vk1 = _mm_set1_epi32(1);
for (k = 0; k < 100; k += 4)
{
__m128i v1 = _mm_loadu_si128(&A[j][k]); // load v1 from A[j][k..k+3] (misaligned)
__m128i v2 = _mm_loadu_si128(&A[r][k]); // load v2 from A[r][k..k+3] (misaligned)
v2 = _mm_mullo_epi32(v2, vcon); // v2 = con * A[r][k..k+3]
v1 = _mm_sub_epi32(v1, v2); // v1 = A[j][k..k+3] - con * A[r][k..k+3]
v1 = _mm_and_si128(v1, vk1); // v1 = (A[j][k..k+3] - con * A[r][k..k+3]) % 2
_mm_storeu_si128(&A[j][k], v1); // store v1 back to A[j][k..k+3] (misaligned)
}
注意:如果您可以保证A的每一行都是16字节对齐,那么您可以将未对齐的加载/存储(_mm_loadu_si128
/ _mm_storeu_si128
)更改为对齐的加载/存储({{1} } / _mm_load_si128
) - 这将有助于提高性能,具体取决于您所针对的CPU。