所以我试图使用SSE函数__mm_load_128
,如果我在某处犯了一些愚蠢的错误,我对SSE很新,请原谅我。
这是代码
void one(__m128i *arr, char *temp)
{
// SSE needs 16 byte alignment.
_declspec (align(16)) __m128i *tmp = (__m128i*) temp;
if (((uintptr_t)tmp & 15) == 0)
printf("Aligned pointer");
else
printf("%d", ((uintptr_t)tmp & 15)); // This prints as 12
arr[0] = _mm_load_si128(tmp);
}
我在visual studio上收到错误
0xC0000005: Access violation reading location 0xFFFFFFFF.
0xFFFFFFFF
看起来不对,我做错了什么。
arr
参数初始化为_m128i arr[5] = { 0 }
替代方法是使用_mm_loadu_128
,它可以正常工作,但据我所知,它应该生成movdqu
指令,但这是生成的汇编
arr[0] = _mm_loadu_si128(tmp);
00D347F1 mov eax,dword ptr [tmp]
00D347F4 movups xmm0,xmmword ptr [eax]
00D347F7 movaps xmmword ptr [ebp-100h],xmm0
00D347FE mov ecx,10h
00D34803 imul edx,ecx,0
00D34806 add edx,dword ptr [arr]
00D34809 movups xmm0,xmmword ptr [ebp-100h]
00D34810 movups xmmword ptr [edx],xmm0
谢谢你们,从答案中我意识到我犯了几个错误。
对齐来源使用_alinged_malloc
使用优化进行编译。
使用C ++强制转换而不是C
答案 0 :(得分:8)
我可以在这里看到三个问题:
one
内时,无法更改arr
或temp
的对齐方式。让我们专注于第2点的第2点 - 有一个指针,指针指向的是什么。我猜你已经知道了这两者之间的区别。
基本上,当你写_declspec (align(16)) __m128i *tmp
时,你告诉程序:
当您在堆栈上分配指针
tmp
时,请确保tmp
的第一个字节分配在一个地址(堆栈上)上,该地址可以被16分割。
太棒了,tmp
本身与16对齐,它根本不影响 tmp指向。您需要temp
指向已对齐数据。
alignas
关键字(alignas(16) char my_buffer[16*100];
)aligned_alloc
或需要_aligned_malloc
的MSVC _aligned_free
。请参阅How to solve the 32-byte-alignment issue for AVX load/store operations? 您无法追溯对齐内存,必须首先对其进行对齐。确保temp
传递的数据已经对齐,或者如果您不需要调用者传递对齐的数据,请使用未对齐的加载/存储。