STLR(B) 是否在 ARM64 上提供顺序一致性?

Does STLR(B) provide sequential consistency on ARM64?

对于对原子数据类型(例如,std::atomic<uint8_t>)的对象执行的存储,GCC 生成:

当目标架构为 x86_64 时。但是,当是ARM64(AArch64)时,在这两种情况下,GCC都会生成相同的指令,即STLRB。没有生成其他指令(例如内存屏障),Clang 也会发生同样的情况。这是否意味着这条被描述为具有 store-relase 语义的指令实际上也提供了顺序一致性?

例如,如果两个内核上的两个线程运行将STLRB存储到不同的内存位置,这两个存储的顺序是否唯一?这样保证所有其他线程都遵守相同的顺序?

我问是因为,根据 this answer,使用 acquire-loads,不同的线程可能会观察到不同的 release-stores。要遵守相同的顺序,需要顺序一致性。

现场演示:https://godbolt.org/z/hajMKnd53

是的,stlr 本身就是商店发布,并且 ldar 不能通过更早的 stlr(即没有 StoreLoad 重新排序)——它们之间的交互满足acq / rel 没有的 seq_cst 要求的一部分。 (ARMv8.3 ldapr 就像 ldar 没有这种交互,只是一个简单的获取负载,允许更有效的 acq_rel。)

所以在ARMv8.3上,seq_cst和acq/rel的区别是在加载端。 8.3 之前的 ARMv8 无法执行 acq / rel 同时仍然允许 StoreLoad 重新排序,因此不幸的是,如果您在 release-store 之后获取加载其他内容,速度会很慢。 ARMv8.3 修复了这个问题,使 acq / rel 与 x86 上一样高效。

在 x86 上,everything 是获取加载或释放存储(因此 acq_rel 是免费的),实现顺序一致性的最不坏的方法是seq_cst 商店的全面障碍。 (您希望原子加载便宜,代码使用默认 seq_cst 内存顺序将很常见。)

C/C++11 mappings to processors 讨论了想要廉价负载的权衡,如果你必须选择负载或存储来附加完整的屏障。)


另外,IRIW 石蕊测试(所有线程同意独立存储的顺序)由 ARMv8 内存模型保证,即使对于发布存储也是如此。它保证是“multicopy-atomic”,这意味着当一个存储对任何其他核心可见时,它也会对 所有 其他核心可见同时。这足以让所有核心就所有商店的总订单达成一致,达到它们通过两次获取负载可以观察到的任何限制。

实际上,这意味着 存储只有在提交到 L1d 缓存后才可见,这是连贯的 。例如,不是通过共享物理核心的逻辑核心之间的存储转发,。 ARMv8 最初在纸面上允许这样做,但 ARM CPUs 从未这样做过。他们加强了内存模型,以简单地保证未来 CPU 不会像那样奇怪。请参阅 简化 ARM 并发:多副本原子 ARMv8 的公理化和操作模型 了解详情。

请注意,这种保证所有线程能够就顺序达成一致的保证适用于 所有 ARM64 上的存储,包括放松。 (在具有连贯共享内存的机器中,可以创建它的硬件机制非常少,因此只有在罕见的 ISA 上 seq_cst 必须实际做任何具体的事情来防止它。)

x86 的 TSO(总存储顺序)内存模型在名称中具有所需的 属性。是的,它更强大,基本上是程序顺序加上带有存储转发的存储缓冲区。 (所以这允许 StoreLoad 重新排序,并且对于核心 ,但没有别的。忽略 NT 存储,以及来自 WC 内存(例如视频 RAM)的 NT 加载...)