当前位置: 首页 > 知识库问答 >
问题:

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

龚凯泽
2023-03-14

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

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

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

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

因此,据我所知,即使指令以无序的方式执行,它们的执行结果也会保存在重新排序缓冲区中,然后以确定的顺序提交给内存/寄存器。

另一方面,已知的事实是,现代CPU可以出于性能加速的目的重新排序内存操作(例如,可以重新排序两个相邻的独立加载指令)。维基百科在这里写了关于它的文章。

你能解释一下这种差异吗?

共有1个答案

空慈
2023-03-14

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

为了使异常准确地回滚到发生故障的指令,而之后没有任何指令已经失效,必须执行顺序提交。无序执行的主要规则是不要破坏单线程代码。如果在没有任何其他机制的情况下允许无序提交(失效),则可能会发生页面错误,而一些后续指令已经执行过一次,和/或一些早期指令尚未执行。这将使处理页面错误后无法以正常方式重新启动执行。

(在正常情况下,无例外情况下,订单发布/重命名和依赖项跟踪会确保正确执行。)

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

(脚注1:《基洛指令处理器:克服内存墙》是一篇关于检查点状态的理论论文,该检查点状态允许在异常发生之前的某个时间点回滚到一致的机器状态,允许更大的无序窗口,而不会出现如此大的ROB。哎呀,还没有主流的商业设计使用过这种方法,但它表明理论上除了str之外还有其他方法。)ictly为了构建一个可用的CPU而退役。

据报道,苹果的M1的故障窗口比x86的同代产品要大得多,但我没有看到任何明确的信息表明它使用的不是非常大的ROB。)

由于每个核心的专用一级缓存都与系统中的所有其他数据缓存一致,因此内存排序是一个关于指令何时读写缓存的问题。这与他们从无序核心退出时是分开的。

从缓存中读取数据时,负载将全局可见。这或多或少是在他们“执行”的时候,而且肯定是在他们退休之前(又称提交)。

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

但即使是为了避免CPU使用存储队列或存储缓冲区来隐藏一级缓存中丢失的存储的延迟。一旦知道存储肯定会发生,故障机器就不需要一直跟踪它,因此存储insn/uop甚至可以在提交到一级缓存之前退出。存储缓冲区将一直保留到一级缓存准备接受它为止。i、 e.当它拥有缓存线时(MESI缓存html" target="_blank">html" target="_blank">一致性协议的独占或修改状态),内存排序规则允许存储现在全局可见。

另请参阅我对写缓存策略的写分配/提取的回答

据我所知,当存储在无序核心中“执行”时,存储的数据会添加到存储队列中,这就是存储执行单元所做的。(存储地址写入地址,存储数据在分配/重命名时将数据写入为其保留的存储缓冲区条目,因此这两个部分中的任何一个都可以首先在单独调度这些部分的CPU上执行,例如Intel。)

负载必须探测存储队列,以便查看最近存储的数据。

对于类似ISA的x86,具有强排序,存储队列必须保留ISA的内存排序语义。i、 e.商店不能与其他商店重新订购,并且在早期加载之前,商店不能在全球可见。(不允许LoadStore重新排序(StoreStore或LoadLoad也不允许),仅允许StoreLoad重新排序)。

David Kanter关于如何以不同于Haswell的方式实现TSX(事务性内存)的文章深入了解了内存顺序缓冲区,以及它是如何与跟踪指令/uop重新排序的重新排序缓冲区(ROB)分离的结构。他首先描述了当前的工作方式,然后讨论了如何修改它以跟踪可以作为一个组提交或中止的事务。

 类似资料:
  • 问题内容: Java的foreach循环是否从第一个对象开始,并且以线性方式工作到结束?例如 是否总是先处理字符串“ Zoe”,然后处理“ Bob”等?没有排序发生?我已经对它进行了测试,但没有找到任何东西,但是我需要保证,在文档中找不到任何东西。 问题答案: 是。顺序不变。这适用于Java类集合框架的所有类型的集合,这些集合实现由for循环使用的迭代器接口。如果要对数组进行排序,则可以使用Arr

  • 我对指令流水线有些怀疑。 我有一个集会

  • 我知道React可能会异步和批量地执行状态更新,以进行性能优化。因此,在调用之后,您永远不能相信会更新状态。但是,您是否信任React按照调用时的顺序更新状态 相同的组件? 不同的组件? 任何有文档支持的答案都是非常感谢的。

  • 问题内容: 我特别想知道PostgreSQL。给出以下人为的示例: 从外部查询返回的名称是否保证与内部查询的顺序相同? 问题答案: 不,在外部查询中按以下顺序排序: 内部(子)查询返回结果集。如果按此顺序进行排序,则保证从内部(子)查询传递到外部查询的中间结果集将按照您指定的方式进行排序,但是在外部查询中不对结果进行排序通过处理内部查询结果集生成的结果集,不能保证以任何方式进行排序。

  • 问题内容: 指令功能的执行顺序是什么?该文档似乎没有解决此问题。 防爆 template / templateUrl(已评估) 控制器 编译 链接 从下面的答案中:http ://plnkr.co/edit/79iyKSbfxgkzk2Pivuak(插件显示嵌套和兄弟指令) 模板被解析 (在编译中对模板所做的更改会扩展到链接功能) 问题答案: 预链接功能:在链接子元素之前执行。执行DOM转换并不安

  • 问题内容: 我正在创建一个JavaScript对象,如下所示 之后,我将它们如下 上面的方法是否按照对象先前的顺序对它们进行了字符串化处理?字符串化后,它们将按照以前的顺序排列为0,1,2 .... 9吗? 问题答案: 文档中没有任何内容可以明确确认数组项的顺序已保留。但是,文档指出,对于非数组属性,不能保证顺序: 非数组对象的属性不能保证以任何特定顺序进行字符串化。不要依赖于字符串化中同一对象内