_mm_load_ps() SSE 内在函数是 defined对齐,如果地址未对齐则抛出异常。不过好像visual studio generates unaligned改为阅读。
由于并非所有的编译器都是一样的,所以这会隐藏错误。如果能够启用实际的对齐操作,那就太好了,即使曾经存在的性能影响似乎不再存在。
换句话说,写代码:
__m128 p1 = _mm_load_ps(data);
目前生产:
movups xmm0,xmmword ptr [eax]
预期结果:
movaps xmm0,xmmword ptr [eax]
(我是微软asked来这里问的)
最佳答案
MSVC 和 ICC 仅在未启用 AVX 的情况下将负载折叠到内存源操作数时使用执行对齐检查的指令,例如 addps xmm0, [rax]
。与 AVX 不同,SSE 内存源操作数需要对齐。但是您无法可靠地控制何时发生这种情况,而且在调试版本中通常不会。
正如 Mysticial 在 Visual Studio 2017: _mm_load_ps often compiled to movups 中指出的那样,另一种情况是NT load/store,因为没有未对齐的版本。
如果您的代码与 clang-cl
兼容,请让 Visual Studio 使用它而不是 MSVC。它是 clang 的修改版本,试图表现得更像 MSVC。但与 GCC 一样,clang 对对齐的内在函数使用对齐的加载和存储指令。
要么禁用优化,要么确保 AVX 未 启用,否则它可能会将 _mm_load_ps
折叠到内存源操作数中,如 vaddps xmm0, [rax]
不需要对齐,因为它是 AVX 版本。如果您的代码还在同一个文件中使用 AVX 内在函数,这可能是个问题,因为 clang 要求您为要使用的内在函数启用 ISA 扩展;即使使用内在函数,编译器也不会为未启用的扩展发出 asm 指令。不同于 MSVC 和 ICC。
即使启用了 AVX,调试版本也应该可以工作,特别是如果您将 _mm_load_ps
或 _mm256_load_ps
放入单独语句中的单独变量,而不是 v=_mm_add_ps( v, _mm_load_ps(ptr));
对于 MSVC 本身,仅出于调试目的(通常对存储有很大的速度损失),您可以用 NT 替代正常的加载/存储。由于它们很特殊,编译器不会将负载折叠到 ALU 指令的内存源操作数中,因此即使在启用了优化的情况下,这也可能适用于 AVX。
// alignment_debug.h (untested)
// #include this *after* immintrin.h
#ifdef DEBUG_SIMD_ALIGNMENT
#warn "using slow alignment-debug SIMD instructions to work around MSVC/ICC limitations"
// SSE4.1 MOVNTDQA doesn't do anything special on normal WB memory, only WC
// On WB, it's just a slower MOVDQA, wasting an ALU uop.
#define _mm_load_si128 _mm_stream_load_si128
#define _mm_load_ps(ptr) _mm_castsi128_ps(_mm_stream_load_si128((const __m128i*)ptr))
#define _mm_load_pd(ptr) _mm_castsi128_pd(_mm_stream_load_si128((const __m128i*)ptr))
// SSE1/2 MOVNTPS / PD / MOVNTDQ evict data from cache if it was hot, and bypass cache
#define _mm_store_ps _mm_stream_ps // SSE1 movntps
#define _mm_store_pd _mm_stream_pd // SSE2 movntpd is a waste of space vs. the ps encoding, but whatever
#define _mm_store_si128 _mm_stream_si128 // SSE2 movntdq
// and repeat for _mm256_... versions with _mm256_castsi256_ps
// and _mm512_... versions
// edit welcome if anyone tests this and adds those versions
#endif
相关:关于使用 MSVC(和 gcc/clang)进行自动矢量化,请参阅 Alex 在 Alignment attribute to force aligned load/store in auto-vectorization of GCC/CLang 上的回答
关于visual-studio - 有没有办法强制 visual studio 从 SSE 内在函数生成对齐的指令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61816101/