对于std::atomic<T>T是基本类型的任何地方:
如果我使用std::memory_order_acq_rel的fetch_xxx操作,以及std::memory_order_acquire用于load操作和std::memory_order_release对store操作盲目(我的意思是,就像重置这些功能的默认内存排序)
std::memory_order_seq_cst(用作默认值)的任何声明操作相同?std::memory_order_seq_cst在效率方面是否与使用不同?存储是释放操作,负载是两者的获取操作.我知道这memory_order_seq_cst意味着要为所有操作强加一个额外的总排序,但是我没有建立一个例子,如果所有的操作memory_order_seq_cst都被替换,那就不是这样了memory_order_acq_rel.
我是否会遗漏某些内容,或者差异仅仅是文档效果,即memory_order_seq_cst如果有人打算不使用更轻松的模型并且memory_order_acq_rel在约束轻松模型时使用,则应该使用?
我正在努力了解 ARM STLR 的确切语义。
根据文档,它具有发布语义。所以如果你有 STLR 商店,你会得到:
[StoreStore][LoadStore]
X=r1
Run Code Online (Sandbox Code Playgroud)
其中X是内存和r1一些寄存器。
问题是释放存储和获取加载无法提供顺序一致性:
[StoreStore][LoadStore]
X=r1
r2=Y
[LoadLoad][LoadStore]
Run Code Online (Sandbox Code Playgroud)
在上述情况下,允许重新排序 X=r1 和 r2=Y。为了使这个顺序一致,需要添加一个[StoreLoad]:
[StoreStore][LoadStore]
X=r1
[StoreLoad]
r2=Y
[LoadLoad][LoadStore]
Run Code Online (Sandbox Code Playgroud)
你通常在商店里这样做,因为装载更频繁。
在 X86 上,普通存储是发布存储,普通加载是获取加载。[StoreLoad] 可以通过 MFENCE 来实现,或者使用LOCK ADDL %(RSP),0Hotspot JVM 中的方式来实现。
当查看ARM文档时,LDAR似乎具有获取语义;所以这将是[LoadLoad][LoadStore]。
但 STLR 的语义很模糊。当我使用 memory_order_seq_cst 编译 C++ 原子时,只有一个 STLR;没有DMB。所以看来STLR比release store有更强的内存排序保证。对我来说,在栅栏层面上,STLR 相当于:
[StoreStore][LoadStore]
X=r1
[StoreLoad]
Run Code Online (Sandbox Code Playgroud)
有人可以解释一下吗?
与我之前的问题类似,请考虑以下代码
-- Initially --
std::atomic<int> x{0};
std::atomic<int> y{0};
-- Thread 1 --
x.store(1, std::memory_order_release);
-- Thread 2 --
y.store(2, std::memory_order_release);
-- Thread 3 --
int r1 = x.load(std::memory_order_acquire); // x first
int r2 = y.load(std::memory_order_acquire);
-- Thread 4 --
int r3 = y.load(std::memory_order_acquire); // y first
int r4 = x.load(std::memory_order_acquire);
Run Code Online (Sandbox Code Playgroud)
是怪异的结果 r1==1, r2==0,并r3==2, r4==0有可能在C ++ 11内存模型下,这种情况下?如果我要全部替换std::memory_order_acq_rel成该std::memory_order_relaxed怎么办?
在x86上,这样的结果似乎是被禁止的,请参见此SO问题,但我一般是在询问C ++ 11内存模型。
奖励问题:
我们都同意,与std::memory_order_seq_cst该怪异的结果不会在C ++ 11被允许。现在,赫伯·萨特(Herb Sutter)在他著名的- …
由于存储负载转发,某些负载指令能否在全局范围内不可见?换句话说,如果加载指令从存储缓冲区中获取其值,则它永远不必从高速缓存中读取。
通常说来,当从L1D缓存读取负载时,该负载在全局范围内可见,因此,未从L1D读取的负载应使其在全局上不可见。
参考下面的代码
auto x = std::atomic<std::uint64_t>{0};
auto y = std::atomic<std::uint64_t>{0};
// thread 1
x.store(1, std::memory_order_release);
auto one = y.load(std::memory_order_seq_cst);
// thread 2
y.fetch_add(1, std::memory_order_seq_cst);
auto two = x.load(std::memory_order_seq_cst);
Run Code Online (Sandbox Code Playgroud)
这里有可能one和two都为 0 吗?
(我似乎遇到了一个错误,在上面的代码运行后,如果one和two都可以保持 0 的值,则可以解释该错误。并且排序规则太复杂,我无法弄清楚上面可以进行哪些排序。)
c++ ×4
c++11 ×3
concurrency ×3
stdatomic ×3
atomic ×2
memory-model ×2
arm ×1
arm64 ×1
c++20 ×1
cpu-cache ×1