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

C++ STLR(B)是否在ARM64上提供顺序一致性?,c++,x86-64,atomic,arm64,memory-model,C++,X86 64,Atomic,Arm64,Memory Model,对于在原子数据类型的对象上执行的存储(例如,std::atomic),GCC生成: 释放存储(std::memory\u order\u release)情况下的MOV指令 顺序一致存储时的指令(std::memory\u order\u seq\u cst) 当目标体系结构为x86_64时。但是,当它是ARM64(AArch64)时,在这两种情况下,GCC生成相同的指令,即STLRB。没有生成其他指令(如内存屏障),而Clang也会发生同样的情况。这是否意味着这个被描述为具有store r

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

  • 释放存储(
    std::memory\u order\u release
    )情况下的MOV指令
  • 顺序一致存储时的指令(
    std::memory\u order\u seq\u cst
当目标体系结构为x86_64时。但是,当它是ARM64(AArch64)时,在这两种情况下,GCC生成相同的指令,即
STLRB
。没有生成其他指令(如内存屏障),而Clang也会发生同样的情况。这是否意味着这个被描述为具有store relase语义的指令实际上也提供了顺序一致性

例如,如果在两个内核上运行的两个线程将使用
STLRB
对不同的内存位置执行存储,那么这两个存储的顺序是否唯一?确保所有其他螺纹遵守相同的顺序

我这样问是因为,根据acquire load,不同的线程可能遵循不同的释放存储顺序。为了遵守相同的顺序,需要顺序一致性


现场演示:

是的,
stlr
是独立的存储版本,
ldar
无法通过早期的
stlr
(即无存储负载重新排序)-它们之间的交互满足acq/rel不具备的seq_cst部分要求。(类似于没有交互的ldar,只是一个简单的获取负载,允许更高效的acq_rel。)

因此,在ARMv8.3上,seq_cst和acq/rel之间的差异在负载侧。ARMv8 8.3之前的版本不能在仍然允许StoreLoad重新排序的情况下执行acq/rel,因此不幸的是,如果在发布store之后获得load其他内容,则速度会很慢。ARMv8.3修复了这一问题,使acq/rel与x86上一样高效

在x86上,所有内容都是一个获取加载或发布存储(因此acq_rel是免费的),实现顺序一致性的最简单方法是在seq_cst存储上设置一个完整的屏障。(您希望原子负载便宜,并且代码使用默认的seq_cst内存顺序是很常见的。)

(讨论了如果必须选择装载或存储以连接完整屏障,则需要廉价装载的权衡。)


另外,IRIW litmus测试(所有线程都同意独立存储的顺序)由ARMv8内存模型保证,即使是发布存储。它保证是“多拷贝原子”,这意味着当存储对任何其他内核可见时,它对所有其他内核同时可见。这就足以让所有的核心就所有存储的总订单达成一致,达到他们通过两个采集负载可以观察到的任何限制

实际上,这意味着存储只有通过提交到L1d缓存才能可见,这是一致的。例如,不是通过共享物理核心的逻辑核心之间的存储转发。ARMv8最初在纸上允许这样做,但从来没有ARM CPU允许这样做。他们加强了内存模型,以确保未来的CPU不会像那样怪异。有关详细信息,请参阅

请注意,所有线程能够就订单达成一致的保证适用于ARM64上的所有存储,包括relaxed。(在具有一致共享内存的机器中,几乎没有硬件机制可以创建它,因此只有在极少数的ISA上,seq_cst才必须实际执行任何特定的操作来防止它。)


x86的TSO(总存储顺序)内存模型在名称中具有所需的属性权限。是的,它更强大,基本上是程序顺序加上带有存储转发的存储缓冲区。(因此,这允许StoreLoad重新排序,对于core to,除此之外没有其他功能。忽略NT存储,并从WC内存(如视频RAM)加载NT…

感谢您的解释。这是否意味着在x86_64上,
mov
执行的存储发布不是“多拷贝原子”?我一直认为ARM的内存模型较弱,但在我看来,在这方面,它实际上更强。@DanielLangr:添加了一段关于x86的内容;它的内存模型有时被称为TSO,Total Store Order,因此您要寻找的保证是正确的:P(并且在更详细地阅读了这个问题后,更新了第一部分,以了解发布存储与x86上的seq_cst不同但与ARM不同的原因。)