目前我已经找到了以下信息:
- SSE和SSE2在Windows 8及更高版本(当然也适用于任何64位操作系统)是必须的。
- AVX仅支持Windows 7 SP1或更高版本。
在Windows上使用SSE3、SSSE3、SSE4.1、SSE4.2、AVX2和AVX-512是否有任何注意事项?
需要澄清的是:我需要确定如果我使用SSE/AVX指令集中的一种,我的程序将在哪些操作系统上运行。
目前我已经找到了以下信息:
在Windows上使用SSE3、SSSE3、SSE4.1、SSE4.2、AVX2和AVX-512是否有任何注意事项?
需要澄清的是:我需要确定如果我使用SSE/AVX指令集中的一种,我的程序将在哪些操作系统上运行。
引入新的架构状态的扩展需要特殊的操作系统支持,因为操作系统必须在上下文切换时保存/恢复更多的数据。因此,从操作系统的角度来看,如果操作系统支持SSE,它不需要额外做任何事情就可以让用户空间代码运行SSSE3指令。
SSE、AVX和AVX512是引入新的架构状态的扩展。
xmm
寄存器(以及MXCSR
用于舍入模式和FP异常状态)。ymm
(其下半部分是旧的xmm
寄存器)。zmm
(扩展了x/ymm
寄存器),并且在64位模式下向量寄存器的数量翻倍:zmm0-zmm31。只有使用AVX-512编码的向量指令(EVEX前缀)才能访问x/y/zmm16..31,因此有趣的是可以在不需要vzeroupper
的情况下使用它们,并且不受其影响。k0..k7
64位掩码寄存器(或在Xeon Phi中没有AVX-512BW时为16位)也是AVX-512中的新功能。您可以使用CPUID指令来检查CPU是否支持SSE或AVX。
当在一个多任务操作系统上使用新扩展且该操作系统在上下文切换时不保存/恢复新的体系结构状态时,为了防止静默数据损坏,如果操作系统没有在控制寄存器中设置操作系统支持位,则SSE指令会出现非法指令故障。因此,在不知道保存/恢复该扩展所需状态的操作系统上,“矢量扩展”将“无法工作”。
CR4.OSFXSR
、CR4.OSXMMEXCPT
等位来保存/恢复SSE状态以进行上下文切换,因为即使读取控制寄存器也是特权级操作,并且没有CPUID位反映该设置。SSE支持如此普及,以至于您必须使用一个非常古老的版本(或自制)操作系统才会出现此问题。
xgetbv
并检查已启用的功能标志,以查看操作系统是否已启用AVX指令以便无故障运行。
使用操作系统提供的函数来检测操作系统支持情况可能比使用内联汇编或特性检测库更容易。例如,Win7SP1引入了
- 使用
CPUID.1:ECX.OSXSAVE位27 = 1
验证操作系统是否支持XGETBV。- 同时,验证
CPUID.1:ECX位28 = 1
(支持Intel AVX)和/或位25 = 1(支持AES)... (以及其他位用于FMA、AES和PCLMULQDQ)- 发出
XGETBV
,并验证位于位1和2的功能启用掩码为11b
(由操作系统启用XMM状态和YMM状态)。
GetEnabledXStateFeatures
函数,同时支持AVX CPU。(很难或者不可能在没有SSE的CPU上找到运行Win7SP1的情况,因此对于SSE,您可以仅检查CPUID和操作系统版本。)IsProcessorFeaturePresent
和GetEnabledXStateFeatures
,因为它们可以告诉你CPU功能是否存在,以及操作系统是否支持它们。如果在CPU中检测到(例如)AVX支持,并且使用AVX指令,但发现每次上下文切换时AVX状态都会被破坏,这将是不好的,因为操作系统没有AVX上下文切换支持。 - Raymond ChenIsProcessorFeaturePresent
未经记录,因此不确定它们需要哪个操作系统。这使得__cpuid
+_xgetvb
成为更有吸引力的解决方案。(还不想在代码的其他可能可移植部分中添加API调用) - Alex Guteniev