visual-studio - 有没有办法强制 visual studio 从 SSE 内在函数生成对齐的指令?

标签 visual-studio visual-c++ sse intrinsics memory-alignment

_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/

相关文章:

visual-studio - Visual Studio 断点保存在哪里?

c++ - Visual Studio : Copying content during build, 无论 cpp 更改如何

c++ - 具有派生模板类和继承成员变量的语法难题

x86 - 如何从 16 x 8 位 __m128i 值中提取 32 x 4 位整数

c++ - 如何启用 SSSE3 内在函数但禁用它们在编译器优化中的使用

visual-studio - 如何在 ASP.NET 5 中执行 Web 部署?

visual-studio - 我在哪里可以找到Visual Studio 2017中的调用堆栈

c# - 字符串的双引号问题

visual-studio-2008 - 如何在vs08中设置_win32_wce的预处理器定义

c++ - 使用 double 运算的快速 SSE 低精度指数