乱序指令执行:是否保留了提交顺序?

时间:2016-09-23 21:47:52

标签: cpu cpu-architecture instructions pipelining dynamic-execution

一方面,维基百科写下了无序执行的步骤:

  
      
  1. 取指令。
  2.   
  3. 指令发送到指令队列(也称为指令缓冲区或保留站)。
  4.   
  5. 指令在队列中等待,直到其输入操作数可用。然后允许该指令离开队列   较早,较旧的说明。
  6.   
  7. 指令发给相应的功能单元并由该单元执行。
  8.   
  9. 结果排队。
  10.   
  11. 只有在所有旧的指令将其结果写回寄存器文件后,才会将此结果写回寄存器文件。这被称为毕业或退休阶段。
  12.   

类似的信息可以在“计算机组织与设计”一书中找到:

  

使程序的行为就像它们在简单的有序运行一样   管道,需要发出指令获取和解码单元   按顺序的指令,允许跟踪依赖关系,以及   提交单元需要将结果写入寄存器和存储器中   程序获取顺序。这种保守模式按顺序调用   提交...今天,所有动态调度的管道使用按顺序提交。

因此,据我所知,即使指令执行是以无序方式完成的,它们的执行结果仍保留在重排序缓冲区中,然后以确定的顺序提交到内存/寄存器

另一方面,已知的事实是现代CPU可以为了性能加速目的而重新排序存储器操作(例如,可以重新排序两个相邻的独立加载指令)。维基百科写了here

你能不能对这种差异有所了解?

1 个答案:

答案 0 :(得分:4)

TL:DR:内存排序与乱序执行不同。它甚至发生在有序流水线CPU上。

有序提交使当前核心自己的代码将本身视为按顺序运行。 (并允许精确的异常,可以回滚到完全错误的指令,没有任何指示后退出)。无序执行的黄金法则是:不要破坏单线程代码。

内存排序完全取决于其他内核所看到的内容。另请注意,您所引用的只是讨论将结果提交到寄存器文件,而不是内存。

由于每个核心的私有L1缓存与系统中的所有其他数据缓存一致,因此内存排序是指令何时读取或写入缓存的问题。这与他们退休时是分开的。

当从缓存中读取数据时,加载变得全局可见。这或多或少是在他们“执行”时,并且在他们退休之前肯定是方式(也就是提交)。

当数据提交缓存时,商店会全局可见。这必须等到它们被认为是非推测性的,即没有异常或中断将导致必须“撤销”商店的回滚。因此,商店可以在从无序核心退役时提交L1缓存。

但即使是有序CPU也会使用存储队列或存储缓冲区来隐藏L1缓存中丢失的存储的延迟。一旦知道它肯定会发生,无序机器就不需要继续跟踪商店,因此商店insn / uop甚至可以在它提交到L1缓存之前退出。存储缓冲区保持不变,直到L1缓存准备好接受它。即它拥有缓存行(M状态为the MESI cache coherency protocol),内存排序规则允许商店现在全局可见。

另请参阅我对Write Allocate / Fetch on Write Cache Policy

的回答

据我了解,商店的数据在无序核心中“执行”时会被添加到商店队列中,这就是商店执行单元所做的事情。

负载必须探测存储队列,以便它们能够看到最近存储的数据。

对于像x86这样具有强排序的ISA,存储队列必须保留ISA的内存排序语义。即商店无法与其他商店重新订购,商店在之前加载时无法全局显示。 (LoadStore reordering isn't allowed (nor is StoreStore or LoadLoad), only StoreLoad reordering)。

David Kanter的article on how TSX (transactional memory) could be implemented in different ways than what Haswell does提供了对内存顺序缓冲区的一些了解,以及它是如何与追踪指令/ uop重新排序的ReOrder缓冲区(ROB)分离的结构。他首先描述了当前的工作原理,然后介绍如何修改它以跟踪可以作为一个组提交或中止的事务。