处理器流水线状态保存
Processor pipeline state preservation
在线程休眠/上下文切换/中断等过程中,是否存在处理器流水线状态(已解码或预取指令)被保存并随后在恢复后重新加载的情况? (可能作为优化)。
据我所知,CPU 这是不可能的。没有执行此操作的界面,也没有 CPU 可以自行执行的条件。将大量内部 CPU 状态转储到 RAM 将花费比节省更多的周期。让 OS 跟踪为此所需的可变大小的 RAM 块只会使开销变得更糟。
顺便说一句,如果有什么值得保存的话,那就是已经执行但还不能退出的指令的结果,因为缓存中没有加载。 (主流 ISA 的所有常见乱序执行设计都使用有序退役来支持精确的异常。已经提出了带有检查点/异常和错误预测回滚的乱序退役。搜索千指令处理器,IIRC。 )
(有缺陷的想法):积极的无序设计可以通过在外部中断到达时延迟写入中断-return地址来避免在上下文切换上浪费太多工作。也就是说,他们可以通过允许管道中已有的一些指令继续执行来假装中断进来的时间晚于实际发生的时间。如果在中断处理程序 return 之前不需要用户 space 指令指针,则 CPU 可以清除管道。
Hrm,这有一个主要的困难,即进入中断处理程序时的寄存器值也取决于体系结构状态,所以这可能行不通。
这个定义。不能用于由 user-space 生成的中断,因为它修复了 return 地址。
对于在使用 monitor / mwait
或其他东西等待自旋锁时让自己进入睡眠状态的线程来说,这不是问题。 mwait
估计是退休后才会生效,之前的工作都做完了才会退休。我认为,CPU 在 mwait
之后积极投机执行会破坏其预期目的。或者 mwait
甚至不冲洗管道,只是为了省电。
这个想法已经提出,但你需要一种密度更大的内存技术,这种技术现在才变得可用。例如,参见本文:
http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=6489970
基本上,他们提出了由一组新的基于忆阻器(电阻性非易失性存储器组件)的锁存器和寄存器组成的管道,可以保存与多个线程对应的多个值。然后控制逻辑可以告诉所有锁存器哪个线程应该处于活动状态,并允许在整个管道中同时进行上下文切换。
请记住,这只会将粒度提高到闩锁级别。具有同步多线程的现代 CPU 已经可以在不同的单元级别上激活不同的线程,而无需上下文切换,只需通过仲裁即可。其他具有固有并行性的单元可能已经在每个周期处理多个线程(例如 - 多端口 ALU)
在线程休眠/上下文切换/中断等过程中,是否存在处理器流水线状态(已解码或预取指令)被保存并随后在恢复后重新加载的情况? (可能作为优化)。
据我所知,CPU 这是不可能的。没有执行此操作的界面,也没有 CPU 可以自行执行的条件。将大量内部 CPU 状态转储到 RAM 将花费比节省更多的周期。让 OS 跟踪为此所需的可变大小的 RAM 块只会使开销变得更糟。
顺便说一句,如果有什么值得保存的话,那就是已经执行但还不能退出的指令的结果,因为缓存中没有加载。 (主流 ISA 的所有常见乱序执行设计都使用有序退役来支持精确的异常。已经提出了带有检查点/异常和错误预测回滚的乱序退役。搜索千指令处理器,IIRC。 )
(有缺陷的想法):积极的无序设计可以通过在外部中断到达时延迟写入中断-return地址来避免在上下文切换上浪费太多工作。也就是说,他们可以通过允许管道中已有的一些指令继续执行来假装中断进来的时间晚于实际发生的时间。如果在中断处理程序 return 之前不需要用户 space 指令指针,则 CPU 可以清除管道。
Hrm,这有一个主要的困难,即进入中断处理程序时的寄存器值也取决于体系结构状态,所以这可能行不通。
这个定义。不能用于由 user-space 生成的中断,因为它修复了 return 地址。
对于在使用 monitor / mwait
或其他东西等待自旋锁时让自己进入睡眠状态的线程来说,这不是问题。 mwait
估计是退休后才会生效,之前的工作都做完了才会退休。我认为,CPU 在 mwait
之后积极投机执行会破坏其预期目的。或者 mwait
甚至不冲洗管道,只是为了省电。
这个想法已经提出,但你需要一种密度更大的内存技术,这种技术现在才变得可用。例如,参见本文:
http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=6489970
基本上,他们提出了由一组新的基于忆阻器(电阻性非易失性存储器组件)的锁存器和寄存器组成的管道,可以保存与多个线程对应的多个值。然后控制逻辑可以告诉所有锁存器哪个线程应该处于活动状态,并允许在整个管道中同时进行上下文切换。
请记住,这只会将粒度提高到闩锁级别。具有同步多线程的现代 CPU 已经可以在不同的单元级别上激活不同的线程,而无需上下文切换,只需通过仲裁即可。其他具有固有并行性的单元可能已经在每个周期处理多个线程(例如 - 多端口 ALU)