引入新架构状态的扩展需要特殊的操作系统支持,因为操作系统必须在上下文切换时保存/恢复更多数据。因此,从操作系统的角度来看,如果操作系统支持 SSE,则无需执行任何额外操作即可让用户空间代码运行 SSSE3 指令。
SSE、AVX 和 AVX512 是引入新架构状态的扩展。
- 上交所推出
xmm
法规(和MXCSR
对于舍入模式和 FP 异常状态)
- AVX介绍
ymm
(下半部分是旧的xmm
regs).
- AVX512推出
zmm
(延长x/ymm
regs),并且还将 64 位模式下的向量寄存器数量加倍:zmm0-zmm31。 x/y/zmm16..31 只能通过向量指令的 AVX-512 编码(EVEX 前缀)访问,因此有趣的是可以在不使用要求vzeroupper https://stackoverflow.com/questions/41303780/why-is-this-sse-code-6-times-slower-without-vzeroupper-on-skylake, and 不受其影响 https://stackoverflow.com/questions/59902442/does-vzeroall-zero-registers-ymm16-to-ymm31.
k0..k7
64 位掩码寄存器(或者 Xeon Phi 中没有 AVX-512BW 的 16 位掩码寄存器)也是 AVX-512 中的新增功能。
您可以使用 CPUID 指令以通常的方式检查 CPU 对 SSE 或 AVX 的支持。
为了防止在多任务操作系统上使用新扩展时出现静默数据损坏(该扩展不会在上下文切换时保存/恢复新的体系结构状态),如果操作系统没有保存/恢复新的体系结构状态,SSE 指令将被错误地视为非法指令。在控制寄存器中设置操作系统支持位 https://stackoverflow.com/questions/31563078/how-do-i-enable-sse-for-my-freestanding-bootable-code。因此,矢量扩展在不知道如何保存/恢复该扩展的必要状态的操作系统上“不起作用”。
对于SSE,可能没有任何干净的独立于操作系统的方法通过设置来检测操作系统是否承诺在上下文切换时保存/恢复 SSE 状态CR4.OSFXSR
, CR4.OSXMMEXCPT
等等位,因为甚至读取控制寄存器也是有特权的 http://www.felixcloutier.com/x86/MOV-1.html,并且没有反映该设置的 CPUID 位。 SSE 支持如此广泛,以至于您必须使用非常古老的版本(或自制软件)操作系统才会出现此问题。
对于 AVX,我们不需要操作系统支持来检测 AVX 是否可用(由硬件支持并由操作系统启用):用户空间可以运行xgetbv
并检查启用功能标志以查看操作系统是否已启用 AVX 指令以无故障运行。
From 英特尔对 AVX 的介绍 https://software.intel.com/en-us/articles/introduction-to-intel-advanced-vector-extensions:
- 使用以下命令验证操作系统是否支持 XGETBV
CPUID.1:ECX.OSXSAVE bit 27 = 1
.
- 同时验证一下
CPUID.1:ECX bit 28=1
(支持英特尔 AVX)和/或位 25=1(AES
支持的) ...(以及 FMA、AES 和 PCLMULQDQ 的其他位)
- Issue
XGETBV
,并验证启用功能的掩码
位 1 和位 2 是11b
(XMM状态和YMM状态由
操作系统)。
调用操作系统提供的函数来检测操作系统支持可能更容易,而不是使用内联 asm 或功能检测库来完成这一切。例如Win7SP1引入GetEnabledXStateFeatures
以及对 AVX CPU 的支持。 (在没有 SSE 的情况下,不太可能或不可能找到运行在 CPU 上的 Win7SP1,因此对于 SSE,您只需检查 CPUID 和操作系统版本即可。)
这也被理解为操作系统的上下文切换将正确保存/恢复完整状态的承诺,尽管当然有错误的、恶意的或深奥的操作系统(也许是协作多任务处理?)可能会有所不同。对于包括 Windows 在内的主流操作系统,这确实意味着 YMM 寄存器将按照您的预期保留其值。
AVX512也是如此:可以检查指令集的CPUID功能位,and检查操作系统是否承诺通过启用 XSETBV 中的正确位来管理上下文切换上的新体系结构状态。 (所以你应该检查 XGETBV)。检查 XGETBV 结果且 0xE6 等于 0xE6。