【发布时间】:2019-04-25 20:42:58
【问题描述】:
我计划实现 SIMD 扩展的运行时检测。是不是如果我发现处理器支持AVX2,也保证支持SSE4.2和AVX?
【问题讨论】:
我计划实现 SIMD 扩展的运行时检测。是不是如果我发现处理器支持AVX2,也保证支持SSE4.2和AVX?
【问题讨论】:
支持最新的英特尔 SIMD ISA 扩展意味着支持以前的 SIMD。
AVX2 肯定意味着 AVX1。
我认为 AVX1 意味着所有 SSE/SSE2/SSE3/SSSE3/SSE4.1/SSE4.2 功能位也必须在 CPUID 中设置。如果没有正式的保证,很多因素都会做出这种假设,并且违反它的 CPU 可能无法在商业上普遍使用。
请注意,popcnt 有自己的功能位,所以理论上你可以拥有一个带有 AVX2 和 SSE4.2 的 CPU,但不是 popcnt,但很多事情将 SSE4.2 视为暗示 popcnt。所以更像是你可以在没有 SSE4.2 的情况下宣传对 popcnt 的支持。
理论上你可以用 AVX 制作一个 CPU(或虚拟机),但它不接受像 pcmpistri 这样的 SSE4.2 指令的非 VEX legacy-SSE 编码,但我认为你会违反 Intel 的保证 AVX 功能位的含义。不确定这是否正式写在手册中,但大多数软件都会这样认为。
但 AVX1 确实 暗示支持 all SSE4.2 和更早的 SIMD 指令的 VEX 编码,例如vpcmpistri 或 vminss
gcc -mavx2 绝对暗示 AVX1 和以前的扩展,但只会发出使用 VEX 编码的代码。不过,它将定义__SSE4_2__ 宏等等,因此 gcc 确实将 AVX2 视为暗示早期的 SSE 扩展和 popcnt,而不是 FMA、AES-NI 或 PCLMUL。即使对于 GCC,这些都是单独的功能。
(实际上,您应该使用gcc -march=native 或gcc -march=znver1 或其他任何方式来启用您的CPU 拥有的所有功能,并为其设置调整选项。不仅仅是-mavx2 -mfma,剩下的调整错误默认值的设置,例如将每个可能未对齐的 256 位加载/存储拆分为 128 位两半。)
(请注意,MSVC 没有那么多 SIMD ISA 检测宏;它有一个用于 AVX,但不适用于所有早期的 SSE* 扩展。MSVC 的模型是围绕程序将执行运行时 CPU 检测而不是正在为本地机器编译。虽然 MSVC 现在确实有 AVX 和 AVX2 选项可以将它们用作基线。)
请注意,AVX512 有点打破传统。 AVX512F 意味着支持 AVX2 及其之前的所有内容,但除此之外,AVX512DQ 不会出现在“之前”或“之后”AVX512ER,例如。您可以(理论上)拥有其中一个,两者都拥有,或者两者都没有。 (实际上,除了 AVX512F,Skylake-X/Cannonlake/etc. 与 Xeon Phi(Knight's Landing / Knight's Mill)只有一点重叠。https://en.wikipedia.org/wiki/AVX-512#CPUs_with_AVX-512
【讨论】:
std::popcount 库实现。如果定义了 AVX,则假定 popcnt 内在函数可用。如果未定义 AVX,它会对 __ISA_AVAILABLE_SSE442 的架构进行运行时检查。换句话说,如果您以 AVX 为目标,则该实现假定这意味着 SSE4.2,包括 popcnt。
如果我们设置编译器选项-mavx2,当我们使用 AVX 或 SSE 内部函数时,GCC 不会出错。所以 GCC 假设 AVX2 标志的存在足以运行 AVX 和 SSE 代码。当然,这并不保证有人不会在没有 SSE 的情况下使用 AVX2 创建 CPU。
【讨论】:
原则上,CPU 可以只支持 AVX2 而不支持任何 SSE4 指令(这并不像听起来那么愚蠢!)。但实际上,如果它支持 AVX2,它也支持 SSE4。
【讨论】:
vpcmpistri 可用。我认为这也意味着非 VEX 编码也可用。从理论上讲,您可以制造不接受非 VEX 编码的 CPU,但我认为您将违反英特尔关于 AVX 功能位所暗示的保证。不过,不确定这是否正式写在手册中。