memory_order_relaxed 和原子 RMW 操作

memory_order_relaxed and Atomic RMW operations

C++ 标准表示对原子的 RMW(读取-修改-写入)操作将对原子变量的最新值进行操作。因此,当从多个线程并发执行时,对这些操作使用 memory_order_relaxed 不会影响 RMW 操作。

我假设仅当为 RMW 操作设置了一些内存屏障或栅栏时,即使指定的内存顺序为 "relaxed",此行为也是可能的。如果我的理解有误,请纠正我,并解释如果没有使用此类内存屏障,这些操作将如何处理最新值。如果我的理解是正确的,那么我是否可以进一步假设使用 Acquire-Release 或 Seq-CST 内存顺序不应该对 RMW 操作产生额外的性能影响,比如 ARM 或 Alpha 等弱顺序架构。提前致谢。

不幸的是,这是对原子内存顺序的常见误解。看,那些(完全)适用于实际的原子操作。它们主要适用于它们周围的其他操作。

例如:

//accessible from anywhere
std::atomic<bool> flag;
int value = 0;

//code in thread 1:
value = 1;
flag.store(true, <order_write>);

//code in thread 2:
bool true_val = true;
while(!flag.compare_exchange_weak(true_val, false, <order_read>);
int my_val = value;

那么,这是在做什么?线程 2 正在等待线程 1 发出 value 已更新的信号,然后线程 2 读取 value.

<order_write><order_read> 不控制如何查看特定原子变量的行为。它控制着 other 设置的 before/after 值如何显示原子操作的行为。

为了使此代码工作,<order_write> 必须 使用至少与 memory_order_release 一样强的内存顺序。并且 <order_read> 必须 使用至少与 memory_order_acquire.

一样强的内存顺序

这些内存顺序会影响 value 的传输方式(或者更具体地说,影响原子写入之前设置的内容)。

wouldn't the condition that "operate on the latest value" require something like a memory barrier?

大多数架构不太可能使用全局内存屏障实现实际的原子修改。它需要非松弛的记忆顺序来做到这一点:它们对作者和读者强加了一个普遍的记忆障碍。

原子操作,如果它们需要内存屏障才能工作,通常会使用本地内存屏障。也就是特定于原子变量地址的barrier。

因此可以合理地假设非松弛的内存顺序比松弛的内存顺序对性能的损害更大。这当然不能保证,但它是一个非常好的一阶近似值。

原子实现是否可能在任何原子操作上使用完整的全局内存屏障?是的。但是如果一个实现求助于基本原子类型,那么架构可能别无选择。因此,如果您的算法需要原子操作,您实际上别无选择。