gcc、clang 和 msvc 的 C++ 自动矢量化要求

Posted

技术标签:

【中文标题】gcc、clang 和 msvc 的 C++ 自动矢量化要求【英文标题】:C++ auto-vectorization requirements for gcc, clang and msvc 【发布时间】:2020-01-08 11:37:27 【问题描述】:

下列说法正确吗?

    使用 GCC 和 clang,如果我使用以下代码编译,我的代码将自动矢量化:

    -O2 -ftree-vectorize -march=XYZ(XYZ为目标指令集:native、SSE、AVX2等) -O3 -march=XYZ

    使用 MSVC,如果我使用以下代码编译,我的代码将自动矢量化:

    /O2

This video 似乎暗示我不需要使用 MSVC 指定架构。那是对的吗?编译器默认使用原生架构,如果找不到向量指令,则在运行时回退到标量操作。

【问题讨论】:

您查阅过文档吗? “visual studio 矢量化”的第一个 Google 结果将我带到解释这一点的页面。 我投赞成票:3. 依赖编译器自动向量化我的代码是错误的 Auto-Vectorizer 生成的指令可能与 /arch 开关指定的指令不同。这些指令由运行时检查保护,以确保代码仍然正确运行。例如,当您编译 /arch:SSE2 时,可能会发出 SSE4.2 指令。运行时检查验证 SSE4.2 在目标处理器上是否可用,如果处理器不支持这些指令,则跳转到循环的非 SSE4.2 版本。 基本上,(我的理解)它会生成多个版本并在运行时决定使用哪个。 这是文档中让我感到困惑的部分。这意味着我的二进制文件非常臃肿,因为它们包含我的程序的两个或三个不同版本。这听起来让我感到惊讶,这就是我首先发布这个问题的原因。 您可以查看反汇编以确切了解它在做什么。还要记住,大多数代码实际上并不能向量化,所以不会添加太多代码。 【参考方案1】:

我不需要使用 MSVC 指定架构。对吗?

是的,这确实是正确的。使用 MSVC,默认情况下,自动矢量化器已启用并选择适当的指令集以实现最快的矢量化。此外,即使您确实指定了arch,自动矢量化器也可能生成与/arch 开关指定的指令不同的指令——如documentation 所述。例如,当你编译/arch:SSE2时,可能会发出SSE4.2指令。

另一方面,与 gcc 或 clang 相比,VS 矢量化器缺少很多功能。

使用 GCC 和 clang,如果我使用 -O2 -ftree-vectorize -march=XYZ 编译,我的代码将自动矢量化? -O3 -march=XYZ ?

不一定,要启用浮点缩减的矢量化,您还需要使用-ffast-math-fassociative-math。但是,一般来说,是的,它会被启用。您可能会在documentation 中找到相同的内容,矢量化由标志 -ftree-vectorize 启用,默认情况下在 -O3 启用

PS:您可以使用https://godbolt.org 来查看这一切!

【讨论】:

以上是关于gcc、clang 和 msvc 的 C++ 自动矢量化要求的主要内容,如果未能解决你的问题,请参考以下文章

gcc 和 clang 抛出“没有匹配的函数调用”但 msvc (cl) 编译并按预期工作

当重载具有多重继承的函数时,GCC称调用它是不明确的,但Clang和MSVC不这样做

C++学习(三四八)CLang GCC

功能无法匹配GLDEBUGPROC,仅在MSVC上(使用相同的glew版本2.1.0,在linux上使用gcc / clang就可以了)

cmake:让mingw(gcc)生成MSVC可用的dll(.lib)----mark亲测有效

Clang如何处理MSVC的编译参数