gpt4 book ai didi

c++ - 非原子负载可以在原子获取负载之后重新排序吗?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:27:21 24 4
gpt4 key购买 nike

众所周知,自 C++11 以来,有 6 个内存顺序,在有关 std::memory_order_acquire 的文档中:

memory_order_acquire

A load operation with this memory order performs the acquire operation on the affected memory location: no memory accesses in the current thread can be reordered before this load. This ensures that all writes in other threads that release the same atomic variable are visible in the current thread.

<强>1。非atomic-load可以在atomic-acquire-load之后重新排序:

即不保证在acquire-atomic-load之后不能重新排序non-atomic-load。

static std::atomic<int> X;
static int L;
...

void thread_func()
{
int local1 = L; // load(L)-load(X) - can be reordered with X ?

int x_local = X.load(std::memory_order_acquire); // load(X)

int local2 = L; // load(X)-load(L) - can't be reordered with X
}

加载 int local1 = L; 可以在 X.load(std::memory_order_acquire); 之后重新排序吗?

<强>2。我们可以认为非atomic-load在atomic-acquire-load之后是不能重新排序的:

一些文章包含一张图片,展示了获取-释放语义的本质。这很容易理解,但会引起混淆。

enter image description here

enter image description here

例如,我们可能认为std::memory_order_acquire不能对任何一系列的Load-Load操作进行重新排序,即使是非atomic-load也不能在atomic-acquire-load之后进行重新排序.

<强>3。非atomic-load可以在atomic-acquire-load之后重新排序:

澄清的好事:获取语义可防止读取-获取的内存重新排序,任何读取或写入操作按程序顺序紧随其后http://preshing.com/20120913/acquire-and-release-semantics/

还有known, that :在强排序系统(x86、SPARC TSO、IBM 大型机)上,release-acquire 排序对于大多数操作是自动的

第 34 页的 Herb Sutter 显示:https://onedrive.live.com/view.aspx?resid=4E86B0CF20EF15AD!24884&app=WordPdf&authkey=!AMtj_EflYn2507c

enter image description here

<强>4。 IE。同样,我们可以认为非atomic-load不能在atomic-acquire-load之后重新排序:

即对于 x86:

  • release-acquire 排序对于大多数操作都是自动的
  • Reads 不会与 any reads 一起重新排序。 (任何 - 即无论是否年长)

那么在 C++11 中非原子加载是否可以在原子获取加载之后重新排序?

最佳答案

我相信这是在 C++ 标准中推理您的示例的正确方法:

  1. X.load(std::memory_order_acquire)(我们称之为“操作 (A)”)可能与 X< 上的某个释放操作同步(操作 (R))- 粗略地说,将值分配给 (A) 正在读取的 X 的操作。<

[atomics.order]/2 An atomic operation A that performs a release operation on an atomic object M synchronizes with an atomic operation B that performs an acquire operation on M and takes its value from any side effect in the release sequence headed by A.

  1. 这种同步关系可能有助于在 L 的某些修改和赋值 local2 = L 之间建立 happens-before 关系。如果 L 的修改发生在 (R) 之前,那么,由于 (R)( A)(A)L 的读取之前排序,L 的修改发生在这次读取之前L.

  2. 但是 (A) 对赋值 local1 = L 没有任何影响。它既不会导致涉及此分配的数据竞争,也不会帮助防止它们。如果程序是无竞争的,那么它必须采用一些其他机制来确保 L 的修改与这次读取同步(如果它不是无竞争的,那么它会表现出未定义的行为和标准对此没有进一步说明)。


在C++标准的四个角落里谈论“指令重排序”是没有意义的。人们可能会谈论由特定编译器生成的机器指令,或者这些指令由特定 CPU 执行的方式。但从标准的角度来看,这些只是无关紧要的实现细节,只要编译器和 CPU 产生可观察到的行为与标准 (the As-If rule) 描述的抽象机的一种可能执行路径一致即可。

关于c++ - 非原子负载可以在原子获取负载之后重新排序吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38677061/

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