C++ 11是ISO c+下的有效输出+;对于x86_64,arm还是其他arch?

C++ 11是ISO c+下的有效输出+;对于x86_64,arm还是其他arch?,c++,multithreading,c++11,memory-barriers,stdatomic,C++,Multithreading,C++11,Memory Barriers,Stdatomic,这个问题是基于 我同意给出的答案。 在x86上,00将永远不会出现,因为a.fetch\u add有一个锁前缀/full barrier,并且加载不能在fetch\u add上重新排序,但在其他架构(如arm/mips)上,它可以打印00。关于x86和arm上的存储缓冲区,我有两个后续问题 我的电脑(core i3 x86_64)上从来没有11,也就是说,11是电脑上的有效输出 在ISO C++中,我是不是很强?strong>Daniel Langr11是x86上的有效输出 现在x86_64

这个问题是基于 我同意给出的答案。 在x86上,00将永远不会出现,因为a.fetch\u add有一个锁前缀/full barrier,并且加载不能在fetch\u add上重新排序,但在其他架构(如arm/mips)上,它可以打印00。关于x86和arm上的存储缓冲区,我有两个后续问题

  • 我的电脑(core i3 x86_64)上从来没有11,也就是说,11是电脑上的有效输出 在ISO C++中,我是不是很强?strong>Daniel Langr11是x86上的有效输出

  • 现在x86_64有一个优势,即fetch_add充当完全屏障

  • 对于arm64,由于cpu指令重新排序,输出有时可能为00

  • 对于arm64或其他一些arch,如果不重新排序,输出是否可以为00?。我的问题 基于此。函数foo的存储缓冲区值 a.fetch\u add(1)不可见的条的a.load()b.fetch\u add(1)对foo的b.load()不可见。因此,我们无需重新排序即可获得00。在不同的牌号下,ISO C++会发生这种情况吗?
//g++-O2-pthread axbx.cpp;虽然[正确];do./a.out | grep“00”;完成
#包括
#包括
#包括
使用名称空间std;
原子a,b;
int reta,retb;
void foo(){
a、 fetch_add(1,内存_order_released);//添加到a存储在cpu0的存储缓冲区中
//a、 存储(1,内存\u顺序\u松弛);
retb=b.load(内存\u顺序\u松弛);
}
空条(){
b、 fetch_add(1,内存_order_released);//添加到b存储在cpu1的存储缓冲区中
//b、 存储(1,内存\u顺序\u松弛);
reta=a.加载(内存顺序松弛);
}
int main(){
线程t[2]{thread(foo),thread(bar)};
t[0]。连接();t[1]。连接();
printf(“%d%d\n”,reta,retb);
返回0;
}

< /代码>

<强>是,ISOC++允许这个< /强>;正如Daniel指出的,一种简单的方法是在RMW之后、加载之前放置一些慢的东西,这样它们在两个线程都有机会增加之前不会执行。这应该是显而易见的,因为它不需要任何运行时重新排序,只需要简单的程序顺序交错。(因此,ISO C++允许使用< SqqcST)<代码> 11代码>,也就是说,您可以单独地逐行地执行每个线程。


您是否想知道如何在x86上创建一个没有延迟循环的实际演示

尝试将原子变量放在单独的缓存线中,以便两个不同的内核可以并行写入它们。

alignas(64) std::atomic<int> a, b;  // the alignas applies to each separately
随意混合,不要将foo2放在foo1之前,也不要将bar2放在bar1之前

i、 e.如果你分别单步走每条线,你永远看不到
00
当然,
mou-released
的全部要点是它可以重新排序。指定“无需重新排序”与说“有顺序cst”相同。

alignas(64) std::atomic<int> a, b;  // the alignas applies to each separately

存储缓冲区的作用是一种重新排序
mo_seq_cst
甚至可以防止这种情况,这是seq_cst的一部分,也是它如此昂贵的原因,特别是对于纯商店操作。

输出
11
是绝对允许的。只需在加载之前添加一些工作:。在您的设置中,不太可能观察到此输出。我将编辑答案。谢谢。你真的关心它可能在一些真正的ISA,或更多的语言律师/什么是ISO C++抽象机?如果是后者,则应将ISAs从标题中删除。(还有更好的措辞:“11”对于不知道问题是关于什么测试用例的任何人来说都没有任何意义。不过,不需要重新排序就可以了,所以我不确定这是否是一个有用的问题。可能只有实际演示部分是有趣的。)
    a.fetch_add(1,memory_order_relaxed);  // foo1
    retb=b.load(memory_order_relaxed);    // foo2

    b.fetch_add(1,memory_order_relaxed); // bar1
    reta=a.load(memory_order_relaxed);   // bar2