我正在尝试使用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:访问地址 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 的强制类型转换。
temp
所指向的缓冲区被正确对齐。另外,在C++代码中应避免使用C风格的类型转换。 - user7860670(__m128i*)
是内嵌函数的标准风格。通常使用reinterpret_cast<__m128i*>(temp)
会显得过于冗长,而且英特尔的内嵌函数名称已经足够长了。此外,__m128i
可以别名任何其他类型,因此它是特殊的。 - Peter Cordes