如何将两个值相乘并以原子方式存储结果?
How to multiply two values and store the result atomically?
假设我的代码中有以下全局变量:
std::atomic<uint32_t> x(...);
std::atomic<uint32_t> y(...);
std::atomic<uint32_t> z(...);
我的任务是将 x 和 y 相乘,然后将结果存储在 z:
z = x * y
我知道在每个对象上调用 store() 和 load() 的幼稚方法是完全错误的:
z.store(x.load() * y.load()); // wrong
这样我执行了三个独立的原子指令:另一个线程可能会滑过并同时更改其中一个值。
我可以选择比较和交换 (CAS) 循环,但它只保证将 z
的旧值与新值 (x*y
) 交换的原子性:我我仍然不确定如何在单个原子步骤中执行整个操作。
我也知道将 x
、y
和 z
包装在一个结构中并使其成为原子在这里是不可行的,因为该结构不适合在单个 64 位寄存器。编译器会在引擎盖下使用锁(如果我在这里错了,请纠正我)。
这个问题只能用互斥锁解决吗?
I'm still not sure how to perform the whole operation in a single, atomic step.
只有当您的体系结构支持诸如“32 位原子乘法”之类的东西(并且您必须在 C++ 标准的设施之外进行它)或一个足够宽的原子来执行64 位上的 RMW 操作。
I'm also aware that wrapping x
, y
and z
inside a struct and make it atomic is not feasible here, as the struct doesn't fit inside a single 64-bit register.
即使它们适合,您仍然需要执行 RMW 操作,因为无论如何您都不太可能有原子乘法。
Is this problem solvable only with a mutex?
如果您的架构支持 lock-free 64 位原子(检查 is_always_lock_free
),您可以将 x
和 y
放在一起并对其执行操作根据需要。
what if the variables were uint64_t
instead, or the operation was way more complex like x * y * w * k / j
?
假设您的体系结构没有 128 位 lock-free 原子,那么您无法以原子方式加载那么多数据。要么设计你的程序,使其不需要(完整的)操作是原子的,要么使用锁,要么寻求一种避免共享状态的方法。
请注意,即使您将某些操作视为原子操作,您也必须意识到在 SMP 系统中您无论如何都会对缓存层次结构施加压力。
假设我的代码中有以下全局变量:
std::atomic<uint32_t> x(...);
std::atomic<uint32_t> y(...);
std::atomic<uint32_t> z(...);
我的任务是将 x 和 y 相乘,然后将结果存储在 z:
z = x * y
我知道在每个对象上调用 store() 和 load() 的幼稚方法是完全错误的:
z.store(x.load() * y.load()); // wrong
这样我执行了三个独立的原子指令:另一个线程可能会滑过并同时更改其中一个值。
我可以选择比较和交换 (CAS) 循环,但它只保证将 z
的旧值与新值 (x*y
) 交换的原子性:我我仍然不确定如何在单个原子步骤中执行整个操作。
我也知道将 x
、y
和 z
包装在一个结构中并使其成为原子在这里是不可行的,因为该结构不适合在单个 64 位寄存器。编译器会在引擎盖下使用锁(如果我在这里错了,请纠正我)。
这个问题只能用互斥锁解决吗?
I'm still not sure how to perform the whole operation in a single, atomic step.
只有当您的体系结构支持诸如“32 位原子乘法”之类的东西(并且您必须在 C++ 标准的设施之外进行它)或一个足够宽的原子来执行64 位上的 RMW 操作。
I'm also aware that wrapping
x
,y
andz
inside a struct and make it atomic is not feasible here, as the struct doesn't fit inside a single 64-bit register.
即使它们适合,您仍然需要执行 RMW 操作,因为无论如何您都不太可能有原子乘法。
Is this problem solvable only with a mutex?
如果您的架构支持 lock-free 64 位原子(检查 is_always_lock_free
),您可以将 x
和 y
放在一起并对其执行操作根据需要。
what if the variables were
uint64_t
instead, or the operation was way more complex likex * y * w * k / j
?
假设您的体系结构没有 128 位 lock-free 原子,那么您无法以原子方式加载那么多数据。要么设计你的程序,使其不需要(完整的)操作是原子的,要么使用锁,要么寻求一种避免共享状态的方法。
请注意,即使您将某些操作视为原子操作,您也必须意识到在 SMP 系统中您无论如何都会对缓存层次结构施加压力。