相关疑难解决方法(0)

是否会在其他线程中始终以相同顺序看到对不同线程中不同位置的两次原子写操作?

与我之前的问题类似,请考虑以下代码

-- 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)在他著名的- …

c++ concurrency memory-model c++11 stdatomic

4
推荐指数
3
解决办法
540
查看次数

为什么这个“std::atomic_thread_fence”起作用

首先我想谈一下我对此的一些理解,如有错误请指正。

  1. aMFENCE在x86中可以保证全屏障
  2. 顺序一致性可防止 STORE-STORE、STORE-LOAD、LOAD-STORE 和 LOAD-LOAD 重新排序

    这是根据维基百科的说法。

  3. std::memory_order_seq_cst不保证防止 STORE-LOAD 重新排序。

    这是根据Alex 的回答,“负载可能会通过早期存储重新排序到不同位置”(对于 x86),并且 mfence 不会总是被添加。

    a是否std::memory_order_seq_cst表示顺序一致性?根据第2/3点,我认为这似乎不正确。std::memory_order_seq_cst仅当以下情况时才表示顺序一致性

    1. 至少一个显式MFENCE添加到任一LOADSTORE
    2. LOAD(无栅栏)和 LOCK XCHG
    3. LOCK XADD ( 0 ) 和 STORE (无栅栏)

    否则仍有可能重新订购。

    根据@LWimsey的评论,我在这里犯了一个错误,如果 和LOAD都是STOREmemory_order_seq_cst则没有重新排序。Alex 可能指出使用非原子或非 SC 的情况。

  4. std::atomic_thread_fence(memory_order_seq_cst)总是产生一个完整的屏障

    这是根据Alex的回答。所以我总是可以替换asm volatile("mfence" ::: "memory")std::atomic_thread_fence(memory_order_seq_cst)

    这对我来说很奇怪,因为memory_order_seq_cst原子函数和栅栏函数之间的用法似乎有很大不同。

现在我在MSVC 2015的标准库的头文件中找到这段代码,它实现了std::atomic_thread_fence

inline void _Atomic_thread_fence(memory_order _Order)
    {   /* …
Run Code Online (Sandbox Code Playgroud)

c++ x86 memory-barriers stdatomic

4
推荐指数
1
解决办法
2212
查看次数

缓存一致性文献一般只涉及存储缓冲区而不是读取缓冲区。然而,不知何故,两者都需要?

在阅读一致性模型(即 x86 TSO)时,作者通常会使用包含大量 CPU、相关存储缓冲区和私有缓存的模型。

如果我的理解是正确的,存储缓冲区可以被描述为队列,CPU 可以在其中放置他们想要提交到内存的任何存储指令。因此,顾名思义,它们是store缓冲区。

但是当我阅读这些论文时,他们倾向于谈论加载和存储的交互,诸如“稍后加载可以通过较早存储”之类的陈述有点令人困惑,因为它们几乎似乎在谈论存储缓冲区将同时具有加载和存储,当它没有时 - 对吗?

所以也必须有一个他们没有(至少明确地)谈论的负载存储。另外,这两者必须以某种方式同步,所以两者都知道什么时候可以从内存加载并提交到内存——或者我是否遗漏了什么?

任何人都可以对此有所了解吗?

编辑:

让我们看一下“内存一致性和缓存一致性入门”中的一段:

为了理解 TSO 中原子 RMW 的实现,我们将 RMW 视为紧跟在存储之后的负载。由于 TSO 的排序规则,RMW 的负载部分无法通过较早的负载。乍一看,RMW 的加载部分可能会传递写入缓冲区中较早的存储,但这是不合法的。如果 RMW 的加载部分通过较早的存储,则 RMW 的存储部分也必须通过较早的存储,因为 RMW 是原子对。但是由于在 TSO 中不允许 store 相互传递,因此 RMW 的负载部分也不能通过较早的 store

进一步来说,

由于 TSO 的排序规则,RMW 的负载部分无法通过较早的负载。乍一看,RMW 的加载部分可能会传递写入缓冲区中较早的存储

所以他们指的是在写入缓冲区中相互交叉的负载/存储(我认为这与存储缓冲区相同?)

谢谢

concurrency x86 cpu-architecture memory-model

4
推荐指数
1
解决办法
235
查看次数