pve*_*jer 1 x86 intel cpu-architecture memory-barriers micro-architecture
由于其 TSO 内存模型,X86 保证所有商店的总顺序。我的问题是是否有人知道这是如何实际实施的。
我对所有 4 个围栏是如何实现的印象很好,所以我可以解释如何保留本地秩序。但是 4 个栅栏只会给 PO;它不会给您 TSO(我知道 TSO 允许旧商店跳到新负载前面,因此只需要 4 个围栏中的 3 个)。
单个地址上所有内存操作的总顺序是一致性的责任。但我想知道英特尔(特别是 Skylake)如何在多个地址的商店上实现总订单。
x86 TSO 内存模型基本上相当于程序顺序加上带有存储转发的存储缓冲区。
大多数由此产生的保证在理论上通过简单的存储缓冲区和一致的共享内存对于硬件来说是相当容易实现的;存储缓冲区将 OoO exec 与有序提交要求(以及缓存未命中存储)隔离,并使推测性地执行存储和重新加载成为可能。
所有核心都可以就所有存储发生的总顺序达成一致。或者更准确地说,内核不能对它们实际观察到的总顺序的任何部分产生分歧。同时存储到 2 个不同的行是同时的,因此任何观察都与假设的总顺序中的任一顺序兼容。
如果使存储对任何其他内核可见的唯一方法使其同时对所有内核可见,则会自动发生这种情况。即通过致力于连贯的 L1d。这使得 IRIW 无法重新排序。(MESI 确保商店不能提交到 L1d,除非它由该核心独家拥有:没有其他核心拥有有效副本。)(观察自己商店的核心需要一个完整的屏障,否则它将通过商店转发观察自己的商店,而不是全局总顺序。典型的 IRIW 试金石测试考虑 4 个总线程,因此没有本地重新加载。)
事实上,这是罕见的任何硬件不具有这种属性; 一些POWER CPU可以在同一物理核心上的 SMT 线程之间进行存储转发,这使得 2 个读者可能对 2 个作者的存储顺序产生分歧(IRIW 重新排序)。尽管 x86 CPU 通常也有 SMT(例如 Intel 的超线程),但内存模型要求它们不能在逻辑内核之间进行存储转发。没关系; 无论如何,它们都会对存储缓冲区进行静态分区。 使用 HT 在一个 Core 上执行的线程之间的数据交换将使用什么?. 以及生产者-消费者在超级兄弟与非超级兄弟之间共享内存位置的延迟和吞吐量成本是多少? 用于实验测试。
唯一发生的重新排序是本地的,在每个 CPU 内核中,在它访问全局一致的共享状态之间。 (这就是为什么本地内存屏障只是让这个核心等待事情发生,例如存储缓冲区耗尽,可以在 x86 TSO 之上恢复顺序一致性。这同样适用于较弱的内存模型,顺便说一句:只是本地重新排序MESI 一致性的顶部。)
这些保证的其余部分分别适用于每个(逻辑)CPU 内核。(关于这如何在内核之间创建同步的问答。)
存储按程序顺序变得可见:从存储缓冲区到 L1d 缓存的有序提交。(存储缓冲区条目在发布/重命名期间按程序顺序分配)。这意味着缓存未命中存储必须停止存储缓冲区,而不是让新存储提交。请参阅为什么退休后 RFO 不中断内存排序?有关此问题的简单心理模型,以及有关 Skylake 可能实际执行的操作的一些详细信息(在等待缓存行到达时将存储未命中的数据提交到 LFB)。
加载不会与以后的存储重新排序:简单:需要加载完全完成(已从 L1d 缓存中获取数据)才能退休。由于退休是有序的,并且商店在它退休之后才能承诺 L1d (变得非投机性),我们可以免费订购 LoadStore 1。
加载按程序顺序从一致缓存(内存)中获取数据。这是难点:加载在执行时访问全局状态(缓存),这与存储缓冲区可以吸收 OoO exec 和有序提交之间的不匹配的存储不同。实际上,让每个负载都依赖于先前的负载,可以防止未命中并扼杀涉及内存的代码乱序执行的许多好处。
在实践中,英特尔 CPU 积极地推测,当架构上允许加载发生时(在执行较早的加载之后),现在存在的缓存行仍将存在。如果不是这种情况,请取消管道(内存顺序错误推测)。为此有一个性能计数器事件。
在实践中,为了追求更高的性能,或者对于推测性的早期加载,一切都可能更加复杂。
(在 C++ 术语中,这至少与 一样强acq_rel,但也涵盖了在 C++ 中可能是 UB 的事物的行为。例如,加载部分重叠最近的存储到另一个线程也可能正在读取或写入的位置,允许这样做core 加载一个从未出现或将出现在内存中的值供其他线程加载。 全局不可见加载指令)
相关问答:
machine_clears.memory_ordering脚注 1:
一些 OoO exec 弱排序 CPU 可以执行 LoadStore重新排序,大概是通过让加载从 ROB 退出,只要加载检查权限并请求缓存行(对于未命中),即使数据实际上没有还没到。需要对未准备好的寄存器进行一些单独的跟踪,而不是通常的指令调度程序。
LoadStore 重新排序实际上在有序管道上更容易理解,我们知道需要对缓存未命中加载进行特殊处理才能获得可接受的性能。 如何通过有序提交实现加载-> 存储重新排序?
| 归档时间: |
|
| 查看次数: |
511 次 |
| 最近记录: |