x86 - 内存屏障的传递性/累积性属性是如何在微架构上实现的?

标签 x86 x86-64 cpu-architecture memory-barriers micro-architecture

我一直在阅读有关 x86 内存模型的工作原理、x86 上屏障指令的重要性以及与其他架构(例如 ARMv8)的比较。在 x86 和 ARMv8 架构中,似乎(没有双关语)内存模型尊重传递性/累积性,即如果 CPU 1 看到 CPU0 的存储,并且 CPU2 看到 CPU1 的存储,则只有当 CPU1 看到 CPU0 的存储时才会发生,那么CPU2也必须看到CPU0的存储。我指的例子是 Paul McKenney 的著名论文第 6.1 节中的示例 1 和 2(虽然很旧,但相关,但他最新的性能 cooking 书 http://www.puppetmastertrading.com/images/hwViewForSwHackers.pdf 中也存在同样的内容)。如果我理解正确的话,x86 使用存储队列(或存储顺序缓冲区)在存储变得全局可见(即写入 L1D)之前对存储进行排序(以及其他微架构优化)。我的问题是 x86 架构(和其他架构)如何实现(微架构上)传递性属性?存储队列确保特定 CPU 的存储按特定顺序全局可见,但是如何确保一个 CPU 进行的存储与不同 CPU 进行的存储排序?

最佳答案

在 x86 上,只有一个一致性域。当所有其他核心提交到 L1d 缓存时,存储将同时对所有其他核心可见。一般来说,与 MESI 一起足以为我们提供所有线程都可以同意的总存储顺序。

一些 ISA(包括 PowerPC)不具有该属性(实际上是因为跨 SMT 线程在物理核心内对退役存储进行存储转发)。因此,在 POWER 硬件上的实践中,另外 2 个读取器可以以不同的顺序看到来自 2 个线程的 mo_relaxed 存储。 Will two atomic writes to different locations in different threads always be seen in the same order by other threads? (大概是 PowerPC 上的障碍阻止了转发。)

ARM 内存模型曾经允许这种 IRIW(独立读取器独立写入器)重新排序,但实际上不存在 ARM 硬件可以做到这一点。 ARM 能够增强其内存模型,以保证所有内核都同意多个其他内核完成的存储的全局顺序。

(存储转发仍然意味着执行存储的核心在它变得全局可见之前就可以立即看到它。当然,核心需要加载排序才能说它们看到了任何内容关于他们观察到的独立写入顺序。)

<小时/>

如果所有核心必须就存储的全局排序达成一致,那么(在您的示例中)从 Core2 看到存储意味着 Core1 一定已经发生,并且您也可以看到它。

(假设 Core2 使用适当的屏障或获取加载或释放存储来确保其存储发生在其加载看到 Core1 的存储之后。)

<小时/>

可能也相关:

关于x86 - 内存屏障的传递性/累积性属性是如何在微架构上实现的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58018486/

相关文章:

c - 16位模式加载地址

assembly - CPUID:为什么某些功能必须将 MISC_ENABLE.LCMV 设置为 0?可以暂时覆盖吗?

c - 在 x64 Visual Studio 中内联汇编函数

c - 我需要一个简单而高效的内存分配算法

linux - printf 和退出表单 C 的 x86 assembly 错误

multithreading - SMT 和超线程 : threads vs process

c++ - 优化算术编码器

c++ - 使用 XNAMATH 优化堆栈分配的对象

assembly - x86 中是否允许访问跨越零边界的内存?

将带有 NT 存储的 64 字节内存复制到 1 个完整缓存行与 2 个连续的部分缓存行