【问题标题】:Intel application: how to transition from integer to floating point mode英特尔应用程序:如何从整数模式过渡到浮点模式
【发布时间】:2023-03-13 20:25:01
【问题描述】:

我知道,当应用程序想要执行浮点运算时,必须将英特尔处理器配置为在浮点模式下工作。每次我需要执行浮点运算时更改模式不是太昂贵吗?谁负责做这个“模式改变”:编译器还是操作系统?考虑到浮点寄存器与整数寄存器是分开的,为什么 FPU 并不总是准备好工作?

【问题讨论】:

  • 现代英特尔处理器通常不会出现这种情况。浮点工作没有单独的模式。为什么你认为有?你在哪里读到这个?它到底说了什么? FPU 和 MMX 操作之间存在排斥,但现在已经过时了。你是这么想的吗?
  • 我在《Linux内核开发第3版》一书中读到:“当用户空间进程使用浮点指令时,内核管理从整数到浮点模式的转换。内核是什么使用浮点指令时必须做的事情因架构而异,但内核通常会捕获一个陷阱,然后启动从整数模式到浮点模式的转换。”
  • 在技术黑暗的时代,人们担心在进程切换时切换出使用进程的纯整数寄存器会浪费时间。为了避免这种开销,许多处理器架构的浮点单元都有一点来记忆自上次显式清除该位以来 FPU 是否已被使用,因此操作系统可以检查它是否需要保留 FPU 状态。此功能尚未在现代操作系统中使用,因为不再值得担心开销。此外,至少在某些英特尔微架构上,这是一个推测执行漏洞。
  • 好的,所以这本书正在讨论为当前进程启用浮点运算的标志。我想这可以称为一种模式,但书上说得不优雅。这个想法是,如果一个进程不使用浮点操作(包括加载和存储),它在浮点寄存器中没有需要保存和恢复的数据。因此,当一个进程首次启动时,内核将其标记为“不允许”使用浮点寄存器。如果一个进程从不使用浮点运算,它会继续它的快乐方式......

标签: linux x86 floating-point context-switch fpu


【解决方案1】:

这不是整数与 FP 模式的对比,只有 x87 和 SSE 控制寄存器位会导致任何 FP 指令错误。 (或 XMM regs 中的 MMX 或整数 SIMD)。

现在大多数进程都使用 XMM regs,例如即使对于 memcpy,上下文切换上的“急切”FPU 保存策略也更有意义,其中 FP/SIMD 寄存器总是在切换到新的用户空间任务之前保存/恢复。 (特别是加载/存储吞吐量相对于中断开销有所提高。)进入内核进行系统调用或中断仍然只保存 GP 整数寄存器,但内核避免使用 FP 指令本身而不触发保存可能脏用户-空间状态。 (所以它很昂贵,只有少数情况下,如 RAID5 / RAID6 和加密驱动程序。)

较旧的 Linux 内核使用“惰性”FPU 保存,在上下文切换时清除这些位,因此任何此类指令都会出错,希望被切换到的新任务能够在没有时间片的情况下结束其时间片故障。在这种情况下,FP/SIMD 寄存器可以保持不变,而用户空间任务的值实际上最后运行了任何 FP/SIMD 指令。

这种故障机制允许内核介入并保存旧的 FP 寄存器,然后再使用其恢复的 FP 寄存器恢复当前任务。但是一旦完成了 FP/SIMD 上下文切换,后面的指令就可以在其剩余的时间片中执行而不会出错。

Eager save/restore 几年前成为默认模式,“懒惰”模式已从 Linux 源代码树中完全删除。同样,因为在深度流水线化的 OoO exec CPU 上中断非常昂贵,而且在给定当前缓存/内存带宽的情况下,保存/恢复 FP regs 并不是那么昂贵。


顺便说一句,您在问题中的描述(除了您的评论)听起来可能是在使用 x87 指令之前需要在 MMX 整数 SIMD 之后需要 emms

这是几乎从不使用 MMX 的几个原因之一,而是使用没有该问题的 SSE2。 (此外,x87 本身几乎从不在 64 位代码中使用,再次支持在 SSE2 寄存器中使用平面寄存器文件而不是堆栈进行标量操作。)

【讨论】:

    猜你喜欢
    • 2012-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-11
    • 2011-04-14
    • 1970-01-01
    • 2014-04-15
    • 2012-09-07
    相关资源
    最近更新 更多