使用 C++ 原子库,我应该使用什么内存顺序进行加载,然后进行比较交换?
Using the C++ atomic lib, what memory order(s) should I use for a load followed by a compare exchange?
例如,多个线程执行 update() 函数:
// Statically allocated
atomic<int> high_water{0};
//...
void update(int meas)
{
int i;
bool replaced;
do
{
i = high_water.load(?);
if (i >= meas)
break;
replaced = high_water.compare_exchange_strong(i, meas, ?, ?);
}
while (!replaced);
// ...
(我正在尝试实现在多个线程中进行的单个测量的共享高水位线。)
compare_exchange_strong
相对于 high_water
是原子的,无论您为它指定什么内存顺序。内存排序仅与 other 内存操作有关。这在很大程度上取决于其他线程如何以及何时需要查看 high_water
。由于 meas
仅在该线程中可见,因此无需考虑其他加载和存储。因此,memory_order_relaxed
是正确的。
作为次要说明,compare_exchange_strong
将第一个参数替换为观察值,因此执行 load
是多余的。
int i = high_water.load(std::memory_order_relaxed);
while (i < meas
&& high_water.compare_exchange_strong(i,
meas,
std::memory_order_relaxed,
std::memory_order_relaxed
)
)
continue;
what memory order(s) should I use for a load followed by a compare exchange?
无法判断,因为您没有显示调用 update()
的代码。
如果您使用 memory_order_relaxed
(或任何比默认值更弱的东西),围绕该调用的内存操作的重新排序在某些平台上是真实的。
high_water
其实可能是用来同步线程间的数据的。 如果您不担心那些可能的重新排序,那么std::memory_order_relaxed
没问题。
一般来说,对于这类操作,我不会使用比默认 (std::memory_order_seq_cst
) 更弱的顺序。
由于 std::compare_exchange_strong
是一个 Read-Modify-Write (RMW) 操作,根据定义它是昂贵的,因为它同步核心之间的原子值,
更改内存顺序不会有太大优势。至少在 X86 上,使用您的代码,编译器将为 std::memory_order_seq_cst
和 std::memory_order_relaxed
发出完全相同的目标代码。
边注,因为你在一个循环中,你可能想使用 compare_exchange_weak()
,这可能会虚假地失败,但这是由循环处理的。
例如,多个线程执行 update() 函数:
// Statically allocated
atomic<int> high_water{0};
//...
void update(int meas)
{
int i;
bool replaced;
do
{
i = high_water.load(?);
if (i >= meas)
break;
replaced = high_water.compare_exchange_strong(i, meas, ?, ?);
}
while (!replaced);
// ...
(我正在尝试实现在多个线程中进行的单个测量的共享高水位线。)
compare_exchange_strong
相对于 high_water
是原子的,无论您为它指定什么内存顺序。内存排序仅与 other 内存操作有关。这在很大程度上取决于其他线程如何以及何时需要查看 high_water
。由于 meas
仅在该线程中可见,因此无需考虑其他加载和存储。因此,memory_order_relaxed
是正确的。
作为次要说明,compare_exchange_strong
将第一个参数替换为观察值,因此执行 load
是多余的。
int i = high_water.load(std::memory_order_relaxed);
while (i < meas
&& high_water.compare_exchange_strong(i,
meas,
std::memory_order_relaxed,
std::memory_order_relaxed
)
)
continue;
what memory order(s) should I use for a load followed by a compare exchange?
无法判断,因为您没有显示调用 update()
的代码。
如果您使用 memory_order_relaxed
(或任何比默认值更弱的东西),围绕该调用的内存操作的重新排序在某些平台上是真实的。
high_water
其实可能是用来同步线程间的数据的。 如果您不担心那些可能的重新排序,那么std::memory_order_relaxed
没问题。
一般来说,对于这类操作,我不会使用比默认 (std::memory_order_seq_cst
) 更弱的顺序。
由于 std::compare_exchange_strong
是一个 Read-Modify-Write (RMW) 操作,根据定义它是昂贵的,因为它同步核心之间的原子值,
更改内存顺序不会有太大优势。至少在 X86 上,使用您的代码,编译器将为 std::memory_order_seq_cst
和 std::memory_order_relaxed
发出完全相同的目标代码。
边注,因为你在一个循环中,你可能想使用 compare_exchange_weak()
,这可能会虚假地失败,但这是由循环处理的。