Performance 为什么SSE指令保留YMM寄存器的上128位?

Performance 为什么SSE指令保留YMM寄存器的上128位?,performance,x86,avx,Performance,X86,Avx,许多英特尔处理器(直到Skylake,除非我错了)在混合AVX-256指令和SSE指令时表现出较差的性能,这似乎是一个问题 根据,这是由于SSE指令被定义为保留YMM寄存器的上128位,因此为了能够通过不使用AVX数据路径的上128位来节省电源,CPU在执行SSE代码时存储这些位,并在输入AVX代码时重新加载它们,存储和加载成本很高 然而,我找不到明显的原因或解释,为什么SSE指令需要保留那些高128位。相应的128位VEX指令(使用它可以避免性能损失)总是清除YMM寄存器的上128位,而不是保

许多英特尔处理器(直到Skylake,除非我错了)在混合AVX-256指令和SSE指令时表现出较差的性能,这似乎是一个问题

根据,这是由于SSE指令被定义为保留YMM寄存器的上128位,因此为了能够通过不使用AVX数据路径的上128位来节省电源,CPU在执行SSE代码时存储这些位,并在输入AVX代码时重新加载它们,存储和加载成本很高

然而,我找不到明显的原因或解释,为什么SSE指令需要保留那些高128位。相应的128位VEX指令(使用它可以避免性能损失)总是清除YMM寄存器的上128位,而不是保留它们。在我看来,当Intel定义AVX架构时,包括将XMM寄存器扩展到YMM寄存器,他们可以简单地定义SSE指令也将清除上面的128位。显然,由于YMM寄存器是新的,因此不可能存在依赖SSE指令来保存这些位的遗留代码,而且在我看来,英特尔很容易就看到了这一点


那么,英特尔定义SSE指令以保留YMM寄存器的高128位的原因是什么?它有用吗?

为了移动站点中的外部资源,我从中提取了相关段落

所有的功劳都归他。
该链接指向了阿格纳·福格在英特尔论坛上提出的一个非常类似的问题

[Fog回应Intel的回答]如果我没弄错的话,您决定有必要拥有两个版本的所有128位指令,以避免 如果中断使用传统XMM指令调用设备驱动程序,则销毁YMM寄存器的上部

英特尔担心,通过使传统SSE指令将XMM寄存器的上部归零,ISR现在会突然 影响新的YMM寄存器。
如果不支持保存新的YMM上下文,则在任何情况下都不可能使用AVX 环境

然而,Fog并不完全满意,他指出,通过简单地使用AVX感知编译器重新编译驱动程序(从而 如果使用了指令),将产生相同的结果

英特尔回答说,他们的目标是避免强迫现有的软件升级 重写

我们无法强迫行业重写/修复其所有现有驱动程序(例如使用XSAVE),也无法保证他们会成功地这样做。例如,考虑到工业从32到64位操作系统的转变中所经历的痛苦!我们从操作系统供应商那里得到的反馈也排除了增加ISR服务的开销,从而在每次中断时增加状态管理开销。我们不想将这两种成本都强加给行业中那些甚至通常不使用宽向量的部分

通过使用两个版本的指令,可以实现对驱动程序中AVX的支持,就像对FPU/SSE的支持一样:

给出的示例与当前场景类似,在当前场景中,ring-0驱动程序(ISR)供应商试图在OSs中使用浮点状态,或意外地将其链接到某个库中,而OSs不会在ring-0自动管理该上下文。这是一个众所周知的bug来源,我只能提出以下建议:

  • 在这些操作系统上,不鼓励驱动程序开发人员使用浮点或AVX

  • 应鼓励驱动程序开发人员在驱动程序验证期间禁用硬件功能(即,环0中的驱动程序可以通过XSETBV()禁用AVX状态)


背景:很早就决定让KeSaveFloatingPointState在Windows x64上不做任何事情,并允许XMM寄存器在不需要额外保存/还原调用的情况下使用,即使在驱动程序中也是如此。显然,这些驱动程序不会意识到AVX或YMM寄存器。

Agner Fog对一个问题有一些见解,这个问题得到了英特尔的回应:@MichaelPetch:很好的发现!如果我正确阅读了Agner的评论,那么额外复杂性的原因是由于Windows的64位调用约定“64位Windows的ABI指定寄存器XMM6-XMM15具有被调用方保存状态”和“额外的复杂性只是为了与现有的x64 Windows设备驱动程序兼容。通过强制Microsoft实施我上面概述的延迟保存解决方案,这个问题本可以用很少的性能成本得到解决“…所以这是微软的错。@Zboson我同意。微软的事情是逆向的:硬件必须适应软件。无论如何,请随意编辑答案,这是一个社区维基,你的评论是一个不错的附加组件:)@Zboson:不完全是这样。在中断处理程序期间,所有YMM REG都可能保持有价值的用户空间状态。内核代码通常避免执行任何FP或SIMD指令,特别是在中断处理程序中,因此只需要保存/还原整数寄存器。如果驱动程序希望在中断处理程序中使用某些XMM寄存器,则可以手动保存/还原它们,而不是调用内核函数来触发保存/还原。这就是问题的根源。将ISR开销添加到始终保存/恢复SIMD状态是错误的。另请参见我的答案的底部/