C++ _declspec(align(16))不将指针对齐到16字节
因此,我尝试使用SSE函数C++ _declspec(align(16))不将指针对齐到16字节,c++,sse,C++,Sse,因此,我尝试使用SSE函数\uuuum\uLoad\u128,我对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) p
\uuuum\uLoad\u128
,我对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:访问冲突读取位置0xFFFFFF。
0xFFFFFFFF
看起来不对,我做错了什么
arr
参数初始化为\u m128i arr[5]={0}
另一种选择是使用\u mm\u loadu\u 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
谢谢各位,从答案中我意识到我犯了几个错误
\u aligned\u malloc
使用C++不强制C
我在这里看到三个问题: <>这代码是严格的C,而不是C++。这本身不是问题,但问题被标记为C++。
one
内部时,无法更改arr
或temp
的对齐方式\u declspec(align(16))\u_m128i*tmp
时,您会告诉程序:
在堆栈上分配指针tmp
时,请确保tmp
的第一个字节分配在可除以16的地址(堆栈上)上
太棒了,tmp
本身与16对齐,它根本不影响tmp指向的内容。您需要temp
指向已对齐的数据。这可以通过以下方式完成:
alignas
关键字(alignas(16)char my_buffer[16*100];
)在堆栈上分配数据对齐的\u alloc
,或MSVC的\u aligned\u malloc
,需要\u aligned\u free
。看您不能反向对齐内存,必须首先对齐内存分配。确保通过
temp
传递的数据已对齐,如果无法要求调用者传递对齐的数据,请使用未对齐的加载/存储 您没有做任何事情来对齐源地址。您正在尝试在不更改存储地址的情况下对齐指针。您应该确保由temp
指向的缓冲区正确对齐。此外,您还应该避免C++代码中的C样式转换。@ VTT:<代码>(μ-M128I*)< /C>是内部的标准样式。code>reinterpret\u cast(temp)通常过于庞大,英特尔的内部函数已经有足够长的名称了。(另外,\uuu m128i
允许别名任何其他类型,因此它是特殊的。)如果您想要外观正常的asm输出,请不要在禁用优化的情况下编译。发射imul-edx,ecx,0
是一种非常糟糕的归零方法edx
。它正在执行movups
加载,但随后溢出到堆栈上的临时位置并重新加载(使用对齐的加载),然后再次存储到它实际想要的结果。就像我说的,如果你希望ASM看起来像你在编写C++时所想象的那样,那么就可以启用优化。这里的悲哀部分是它不会崩溃到MSVC和ICC的新版本,因为它们通常会使用不对齐的访问。因此,与崩溃相反,您很难检测到性能问题。不幸的是,MSVC DEVS说这是设计的。如果你把它编译成C++,那就是C++。可以说它是用类似C的风格编写的,但这不会改变编译器对它的解释方式。C和C++之间有细微的差别。也许这个代码来自C示例,OP在C++中使用它。你也可以写代码“> > ASMASEAX,8 } /CODE,并在C++程序中编译它,但是这不构成汇编语言C++。我同意这一点,但仍然认为你应该用不同的方式来描述你的点1。如果你想批评C++风格中C风格的用法,当然可以。但这并不意味着C.Union类型双关语仍然是未定义的行为(除了我认为MSVC确实定义了它,和GNU C++一样)。但是你可以说,在某些方面,它确实使MSV++程序的ASM部分。MSVC内联asm与MASM的区别很小(例如,它接受0xdeadbeefh
以及0deadbeefH
)