gpt4 book ai didi

c++ - 原子操作传播/可见性(原子负载与原子 RMW 负载)

转载 作者:太空狗 更新时间:2023-10-29 20:33:27 27 4
gpt4 key购买 nike

语境

我正在写一个线程安全的 protothread/coroutine library在 C++ 中,我正在使用原子学使任务切换无锁。我希望它尽可能高效。我对原子和无锁编程有一般的了解,但我没有足够的专业知识来优化我的代码。我做了很多研究,但很难找到我的具体问题的答案:不同内存顺序下不同原子操作的传播延迟/可见性是多少?

当前假设

我读到对内存的更改是从其他线程传播的,以这种方式它们可能变得可见:

  1. 以不同的顺序给不同的观察者,
  2. 一些延迟。

我不确定这种延迟的可见性和不一致的传播是否仅适用于非原子读取,或者也适用于原子读取,这可能取决于使用的内存顺序。当我在 x86 机器上开发时,我无法在弱序系统上测试行为。

无论操作类型和使用的内存顺序如何,所有原子读取是否总是读取最新值?

我很确定所有读取-修改-写入 (RMW) 操作总是读取任何线程写入的最新值,无论使用的内存顺序如何。 顺序一致操作似乎也是如此,但前提是对变量的所有其他修改也顺序一致。据说两者都很慢,这对我的任务不利。如果不是所有原子读取都获得最新值,那么根据我目前的理解,我将不得不使用 RMW 操作来读取原子变量的最新值,或者在 while 循环中使用原子读取。

写入的传播(忽略副作用)是否取决于内存顺序和使用的原子操作?

(只有当上一个问题的答案是并非所有原子读取总是读取最新值时,这个问题才有意义。请仔细阅读,我在这里不问副作用的可见性和传播。我只关心原子变量本身的值。) 这意味着根据用于修改原子变量的操作,可以保证任何后续原子读取都接收到最近的值多变的。因此,我必须在保证始终读取最新值的操作之间做出选择,或者使用宽松的原子读取,以及这种特殊的写入操作,以保证对其他原子操作的修改的即时可见性。

最佳答案

原子锁是免费的吗?

首先,让我们摆脱房间里的大象:使用atomic在您的代码中并不能保证无锁实现。 atomic只是无锁实现的插入者。 is_lock_free() 会告诉您对于 C++ 实现和您正在使用的底层类型,它是否真的是无锁的。

最新值是多少?

术语“最新”在多线程世界中是非常模糊的。因为对于一个可能被操作系统休眠的线程来说,什么是“最新的”,对于另一个事件的线程来说可能不再是最新的。

std::atomic 唯一的保证是通过确保 R, M and RMW 来防止赛车条件在一个线程中对一个原子执行的操作以原子方式执行,没有任何中断,并且所有其他线程都看到之前的值或之后的值,但看不到中间值。所以atomic通过在同一原子对象上的并发操作之间创建顺序来同步线程。

您需要将每个线程视为一个具有自己时间的平行宇宙,并且不知道平行宇宙中的时间。就像在量子物理学中一样,你在一个线程中唯一能知道的关于另一个线程的就是你能观察到的(即宇宙之间“之前发生过”的关系)。

这意味着你不应该把多线程时间想象成所有线程都有一个绝对的“最新”时间。您需要将时间视为相对于其他线程的时间。这就是为什么原子不创建绝对最新的,而只确保原子将具有的连续状态的顺序排序。

传播

传播不依赖于内存顺序,也不依赖于执行的原子操作。 memory_order是关于围绕原子操作的非原子变量的顺序约束,这些原子操作看起来像栅栏。关于这是如何工作的最好的解释当然是 Herb Sutters presentation ,如果您正在处理多线程优化,那绝对值得花一个半小时。

虽然特定的 C++ 实现可能会以影响传播的方式实现某些原子操作,但您不能依赖任何此类观察,因为无法保证传播以相同的方式工作编译器的下一个版本或另一个 CPU 架构上的另一个编译器。

但是传播重要吗?

designing lock-free algorithms ,很容易读取原子变量以获得最新状态。但是,尽管这种只读访问是原子的,但紧随其后的操作却不是。因此,以下指令可能会假定一个已经过时的状态(例如,因为线程在原子读取后立即进入休眠状态)。

if(my_atomic_variable<10)并假设您读到 9。假设您处于最佳可能世界中,并且 9 将是所有并发线程设置的绝对最新值。将其值与 <10 进行比较不是原子的,所以当比较成功并且if分支机构,my_atomic_variable可能已经有一个新值 10。而且无论传播速度有多快,即使读取保证始终获得最新值,这种问题也可能发生。我什至没有提到 ABA problem然而。

读取的唯一好处是避免数据竞争和 UB。但是如果你想跨线程同步决策/ Action ,你需要使用RMW,比如compare-and-swap (例如 atomic_compare_exchange_strong )以便原子操作的排序产生可预测的结果。

关于c++ - 原子操作传播/可见性(原子负载与原子 RMW 负载),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55079321/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com