【问题标题】:Detecting SIMD instruction sets to be used with C++ Macros in Visual Studio 2015在 Visual Studio 2015 中检测要与 C++ 宏一起使用的 SIMD 指令集
【发布时间】:2017-04-07 00:40:54
【问题描述】:

所以,这就是我想要完成的。在我的 C++ 项目中,必须使用 Microsoft Visual Studio 2015 或更高版本进行编译,根据用户 CPU 中可用的最新 SIMD 指令集,我需要一些代码具有不同的版本,其中: SSESSE2SSE3SSSE3SSE4.1SSE4.2AVXAVX2AVX512

由于我现在要寻找的是编译时 CPU 调度,我的第一个猜测是使用编译器宏可以轻松完成。然而,令我惊讶的是,在 VS2015 中很难找到关于如何使用宏实现这种 CPU 调度的信息。

例如,前一个问题“Detect the availability of SSE/SSE2 instruction set in Visual Studio”包含有关如何检测 x86 代码的 SSE 和 SSE2 的信息,但不适用于 x64 代码。虽然,他们引用了这个微软的文档:http://msdn.microsoft.com/en-us/library/b0084kay.aspx

在那里,我们只有关于如何检测 SSE、SSE2、AVX 和 AVX2 是否在编译器中启用的信息 - 不完全是 CPU 是否支持它们。此外,其他指令集(如 SSE3、SSSE3、SSE4.1、SSE4.2 和 AVX512)完全没有。

所以,我的问题变成了:我如何才能像其他编译器一样通过宏检测用户的 CPU 是否支持这些指令集,但使用 Microsoft Visual Studio 2015?

【问题讨论】:

  • 除非您只打算在您编译的同一台机器上运行,否则支持的 CPU 功能集不是编译时常量,因此不能是宏。但是,如果您是,只需执行 gcc 的 -march=native 的 MSVC 等效项,并查看通常的目标功能宏,如 #ifdef __AVX__
  • @PeterCordes 但这正是问题所在。除了__AVX____AVX2__ 之外没有宏。我的问题的全部意义在于调查人们是如何实现这一目标的,因为 Vistual Studio 似乎缺少这样的宏。
  • @PeterCordes 尽管这很奇怪,但似乎确实如此。 MSVC 的宏列表仅包括 AVX 和 AVX2 的宏。正如问题中所链接的,SSE2 的间接宏。这就是我的问题的由来:很难找到这方面的信息。关于你的问题,我两个都需要。对于这一部分,我需要编译时调度。但对于其他部分,我需要运行时调度——在这种情况下,我根据英特尔的手册使用__cpuid,它在大多数情况下都运行良好。
  • 要启用它们,当然 CPU 支持它们。这里的问题是说“CPU”,就像只有一个一样。如果您在旧计算机上运行编译器,构建只需要在新计算机上运行的二进制文件,您将启用 AVX。生成的二进制文件不会在构建它的计算机上运行,​​但它可以很好地创建它。在构建系统和编译器术语中,我们谈论“目标”与“主机”。因此启用 AVX 是一个目标选项,宏可以检测目标的基线(即启用以供编译器使用)。
  • "Microsoft 的 VS 宏检测选项中是否启用了 AVX 或 AVX2。要启用它们,当然 CPU 支持它们。" 不,这是一个错误。您可以在非 AVX CPU 上编译 AVX 代码。 “编译 AVX 代码”只是意味着编译器发出编码 AVX 操作的字节字符串。编译不涉及执行发出的字节字符串。

标签: c++ visual-studio-2015 sse avx instruction-set


【解决方案1】:

您面临的问题是 Visual Studio 在历史上是为软件供应商设计的。编译自己的软件的想法根本不在 Microsoft 的 DNA 中。

实际结果是微软几乎不关心构建机器的处理器。这不太可能是用于运行软件的处理器。

从好的方面来说,这也意味着微软不会遭受长期存在的 Linux 问题,即构建系统库被假定存在于目标计算机上。在 Windows 10 上构建 Windows 7 即可。

例如,编译器也不允许您启用最高 SSE4.1。您只能使用/arch:avx 或不使用。此外,该选项仅定义 __AVX__,而不是像 __SSSE3__ 这样的常用宏,gcc/clang/icc 定义以指示目标支持 AVX 隐含的先前指令集。

【讨论】:

  • 你能理解 OP 关于 MSVC defines __AVX__ but not for example __SSSE3__ 的说法吗?这似乎不太可能,除非相同的信息存在于不同名称的宏中。另外,我不确定这个问题是否在问这个问题,或者如何实际做与gcc -march=native 等效的操作(您的回答是 Visual Studio 不支持)。
  • @PeterCordes:不,它是正确的。有一个__AVX__ 宏,但没有__SSSE3__ 宏。这是合乎逻辑的:前者匹配/arch:AVX 命令行选项,但没有/arch:SSSE3 选项。 (有一个 `/arch:SSE2 选项,但不适用于 x64)
  • 我不确定为什么 MSVC 有 /arch:AVX2 并定义了 __AVX2__。我一直想知道他们为什么这样做,因为例如他们没有定义 SSE4.1。 /arch:AVX 为了指定 vex 编码是有意义的,但为什么是 /arch:AVX2? GCC 根据您定义的指令集优化代码,但 MSVC 不会为 SSE 执行此操作,除非在某些情况下(例如自动矢量化)它们实际上构建了代码以检测 SSE4.1,因此代码适用于 SSE2 并针对 SSE 4.1 进行了优化以及。使用 GCC,您可以指定 -msse4.1,代码会为此优化,但不适用于 SSE2。
  • 这是 MSVC 自动检测 SSE4.2 并将其与自动矢量化一起使用的示例stackoverflow.com/a/25495173/2542702
猜你喜欢
  • 1970-01-01
  • 2021-06-29
  • 2018-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-01
  • 1970-01-01
相关资源
最近更新 更多