我计划实现对SIMD扩展的运行时检测。如果我发现处理器支持AVX2,是否可以保证它也支持SSE4.2和AVX?
支持更新的英特尔SIMD ISA扩展意味着支持以前的SIMD扩展。
AVX2明确意味着支持AVX1。
我认为AVX1意味着CPUID中还必须设置所有SSE/SSE2/SSE3/SSSE3/SSE4.1/SSE4.2特性位。虽然没有正式保证,但许多东西都基于这个假设,违反此假设的CPU可能不适用于一般用途。
请注意,popcnt
有自己的特性位,所以理论上你可以拥有支持AVX2和SSE4.2的CPU,但不支持popcnt
,但很多东西将SSE4.2视为支持popcnt
。因此,更像是你可以宣传支持popcnt
而不支持SSE4.2。
理论上,你可以制造一款带有AVX的CPU(或虚拟机),但不接受非VEX遗留SSE4.2指令编码,比如pcmpistri
。但我认为这将违反英特尔关于AVX特性位含义的保证。虽然不确定是否在手册中正式写明,但大多数软件都会假设如此。
但是AVX1确实意味着支持对所有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作为基准的选项。)
-mavx2
,GCC就不会在使用AVX或SSE内部函数时报错。因此,GCC认为存在AVX2标志就足以运行AVX和SSE代码。当然,这并不保证有人不会创建一个带有AVX2但没有SSE的CPU。原则上,CPU可以只支持AVX2而不支持任何SSE4指令(这并不像听起来的那么愚蠢!)。但实际上,如果它支持AVX2,也会支持SSE4。
vpcmpistri
。我认为它还意味着非VEX编码也可用。理论上,您可以制造一个不接受非VEX编码的CPU,但我认为您将违反英特尔关于AVX功能位所示内容的保证。不确定是否在手册中正式写下了这一点。 - Peter Cordes
std::popcount
。如果定义了AVX,则假定可用popcnt内部函数。如果未定义AVX,则对__ISA_AVAILABLE_SSE442
进行运行时架构检查。换句话说,如果您的目标是AVX,则实现会假定包括popcnt在内的SSE4.2。 - Adrian McCarthy