3

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

有一个页面谈论启用一些 simd,例如 SSE2、AVX、AVX2 https://docs.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 也默认启用吗?

4

2 回答 2

4

VC++ 编译器没有你想象的那么聪明。以下是这些设置的工作原理。

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

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

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

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

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

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

于 2020-09-25T04:40:28.263 回答
0

显然,您可以/arch:以未记录的方式将选项作为/d2...选项传递。喜欢/d2archAVX

/d2archSSE42以这种方式被接受(但不是 SSE41 或 SSE3)。

@Peter 在评论中指出了一个有影响的案例/d2archSSE42https ://godbolt.org/z/EsjW4vTne

于 2021-09-25T17:18:54.590 回答