如何在 MSVC 中启用 SSE4.1 和 SSE3(但不是 AVX)

kni*_*pku 4 sse simd visual-c++ sse4

我正在尝试使用 MSVC 启用不同的 simd 支持。

有一个页面讨论启用一些simd,例如SSE2、AVX、AVX2 https://learn.microsoft.com/en-us/cpp/build/reference/arch-x86?redirectedfrom=MSDN &view=vs- 2019年

但是,它没有提到如何启用其他 simd 优化,例如 SSE4.1、SSE4.2、SSE3 是否可以在不启用 AVX 的情况下启用这些优化?

另外,看起来在 MSVC2017 /arch:SSE2 不再受支持/需要,我可以假设 SSE3/SSE4.1/SSE4.2 默认情况下也是启用的吗?

Soo*_*nts 5

VC++编译器没有你想象的那么聪明。Here\xe2\x80\x99 介绍了这些设置的工作原理。

\n

当您构建 32 位代码并启用 SSE1 或 SSE2 时,它会自动矢量化为相应的指令集。

\n

当您\xe2\x80\x99构建64位代码时,SSE1和SSE2都是指令集的一部分,世界上所有AMD64处理器都需要支持这两者。这就是为什么你\xe2\x80\x99 收到 /arch:SSE2 警告的原因。

\n

当您设置 AVX 时,编译器会做两件事,启用自动矢量化为 AVX1,还将指令编码(对于所有这些,SSE、AVX,手动矢量化和自动矢量化)从旧版切换到VEX。VEX 是个好东西,可以将未对齐的 RAM 读取融合到其他指令中。它还解决了可能影响性能的依赖性问题,VEX 编码将vaddps xmm0, xmm0, xmm1的高 16 字节清零ymm0,而传统编码addps xmm0, xmm0, xmm1则将数据保留在那里。

\n

当您设置 AVX2 时,它会进行一些小的优化,最值得注意的是_mm_set1_epi32可能会编译成vpbroadcastd. 还可以像 AVX1 一样将编码切换为 VEX。

\n

注意我用粗体标记自动。Microsoft 编译器不执行运行时调度或 cpuid 检查,并且自动矢量化器不使用 SSE3 或 4.1。如果您\xe2\x80\x99正在编写手动矢量化代码,编译器将\xe2\x80\x99t执行回退,将发出您要求的任何指令。如果存在,AVX/AVX2 设置仅影响其编码。

\n

如果您想编写使用 SSE3、SSSE3、SSE 4.1、FMA3、AES、SHA 等的手动矢量化代码,则不需要启用任何内容。您只需要包含相关标头,并且最好确保在运行时 CPU 拥有它们。对于最后一部分,我通常__cpuid在启动时尽早调用并检查这些位,这是为了显示有关不支持的 CPU 的可理解的错误消息,而不是稍后硬压垮。

\n