【问题标题】:How can we expect a program to complete in order?我们怎么能期望一个程序按顺序完成?
【发布时间】:2021-01-24 07:53:02
【问题描述】:

大多数现代微处理器都存在乱序执行。我们怎么能期望程序按照程序员编写的顺序完成?

【问题讨论】:

    标签: cpu cpu-architecture microprocessors


    【解决方案1】:

    是的,当然,您不能只在架构寄存器中碰巧出现的任何寄存器值上以任意顺序运行指令。 一条指令只有在其正确输入准备就绪时才能执行。为尽可能多的“未来”指令找到正确的时间是保持执行单元工作的关键,@ 987654321@.

    在分配/重命名期间设置指令之间的依赖关系跟踪,因为指令从前端复制(按程序顺序)到后端。在分配/重命名期间,RAT(寄存器分配表)将架构寄存器映射到物理寄存器,从而允许使用同一架构寄存器的多个独立 dep 链同时执行。


    也许你在考虑这个倒退。 ISA(例如 x86-64 或 ARMv8)定义了一组机器指令如何执行的规则,通常是一种串行模型,其中一条指令在下一条指令开始之前完全执行完毕。 (确实存在具有一些显式并行性的 ISA,例如 VLIW,或 The Mill 的延迟可见性负载,这些负载在一些固定指令之后变得可见,有助于隐藏有序 CPU 上的负载延迟。仍然有很好的- 定义的规则。)

    要为这样的 ISA 运行软件,硬件必须实施所有在纸上保证的规则。 乱序执行的基本规则是保持单线程按程序顺序执行指令的错觉1。这是成为有效/无故障 x86 或 ARM CPU 的必要部分。

    (请参阅Observing x86 register dependencies - 任何未重命名的架构状态通常需要在修改时序列化管道,因此请确保任何需要旧值的指令已经完成。)

    这很像 C 的“好像”优化规则:只要可观察到的结果仍然相同,您就可以做任何您想做的事情,但对于 CPU 架构师而不是编译器。

    正如 Modern Microprocessors A 90-Minute Guide! 所说:如果处理器要乱序执行指令,则需要记住这些指令之间的依赖关系。(如果您还没有阅读过,那么您绝对应该去阅读它;它是理解任何更高级内容的一个非常好的基线,而且它本身涵盖了很多领域。强烈推荐。)

    这就是为什么 OoO exec 需要这么多晶体管用于大型调度程序和重排序缓冲区 (ROB) 来跟踪重排序以及指令之间的依赖关系。 (在计算机架构术语中,RAW hazards:写入后读取,其中一条指令写入一个寄存器,然后一条指令读取该寄存器。Register renaming 隐藏了 WAR 和 WAW 危险。)

    脚注 1:OoO 执行程序尝试维护其他线程观察到的memory accesses 的顺序。即使是按顺序的 CPU 也可以进行内存重新排序,因此软件总是需要注意线程间通信,使用栅栏指令和/或获取加载/释放存储或其他内容,具体取决于 ISA。

    另见

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-08
      相关资源
      最近更新 更多