与(简单地)发生在'之前相比,'强烈发生在'之前有什么意义呢?

What is the significance of #39;strongly happens before#39; compared to #39;(simply) happens before#39;?(与(简单地)发生在#39;之前相比,#39;强烈发生在#39;之前有什么意义呢?)
本文介绍了与(简单地)发生在'之前相比,'强烈发生在'之前有什么意义呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

该标准定义了几个"在此之前发生"关系,这些关系将良好的旧"在此之前排序"扩展到多个线程:

推荐答案

这是我目前的理解,可能不完整或不正确。如能核实,将不胜感激。


C++20已将strongly happens before重命名为simply happens before,并为strongly happens before引入了更宽松的新定义,从而降低了排序。

Simply happens before用于推断代码中是否存在数据竞争。(实际上,这显然是"以前发生的",但如果没有消费操作,这两种操作是等价的,标准不鼓励使用消费操作,因为大多数(所有?)主要编译器将它们视为获取。)

较弱的strongly happens before用于推断seq-cst操作的全局顺序。


此更改是在提案P0668R5: Revising the C++ memory model中引入的,该提案基于Lahav等人的论文Repairing Sequential Consistency in C/C++11(我没有完全阅读)。

该提案解释了做出更改的原因。长话短说,大多数编译器在Power和ARM体系结构上实现原子的方式在极少数边缘情况下被证明是不一致的,而且修复编译器有性能成本,因此他们改为修复标准。

仅当您在同一原子变量上混合使用seq-cst操作和获取-释放操作时(即,如果获取操作从seq-cst存储区读取值,或seq-cst操作从发布存储区读取值),更改才会影响您。

如果您不以这种方式混合操作,则不会受到影响(即可以将simply happens beforestrongly happens before视为等效)。

更改的要点是seq-cst操作与相应的获取/释放操作之间的同步不再影响此特定seq-cst操作在全局seq-cst顺序中的位置,但同步本身仍然存在。

这使得此类seq-cst操作的seq-cst顺序非常没有意义,请参见下面的内容。


提案如下所示,我试着解释一下我对它的理解:

atomic_int x = 0, y = 0;
int a = 0, b = 0, c = 0;
// Thread 1
x.store(1, seq_cst);
y.store(1, release);
// Thread 2
b = y.fetch_add(1, seq_cst); // b = 1 (the value of y before increment)
c = y.load(relaxed); // c = 3
// Thread 3
y.store(3, seq_cst);
a = x.load(seq_cst); // a = 0

注释指示此代码可以执行的一种方式,这是标准过去禁止的(在此更改之前),但实际上可能会发生在受影响的体系结构上。

执行过程如下:

.-- T3 y.store(3, seq_cst);                   --.                 (2)
|        |                                      | strongly
|        | sequenced before                     | happens
|        V                                      | before
|   T3 a = x.load(seq_cst); // a = 0    --.   <-'                 (3)
|                                         : coherence-
|                                         : ordered
|                                         : before
|   T1 x.store(1, seq_cst);             <-'   --. --.             (4)
|        |                                      |st |
|        | sequenced before                     |h  |
|        V                                      |b  |
| . T1 y.store(1, release);                   <-'   |
| |      :                                          | strongly
| |      : synchronizes with                        | happens
| |      V                                          | before
| > T2 b = y.fetch_add(1, seq_cst); // b = 1  --.   |             (1)
|        |                                      |st |
|        | sequenced before                     |h  |
|        V                                      |b  |
'-> T2 c = y.load(relaxed); // c = 3          <-' <-'

其中:

  • 右侧的括号数字显示全局序号-CST顺序。

  • 左侧的箭头显示值如何在某些加载和存储之间传播。

  • 中间的箭头显示:

    • 'Sequenced before',很老的单线程求值顺序。
    • ‘同步于’,释放-获取同步(seq-cst加载计数为获取操作,seq-cst存储计数为释放操作)。

    这两个加在一起构成"简单地发生在此之前"。

  • 右侧的箭头基于中间的箭头,它们显示:

    • 新定义的"强发生在此之前"关系。

    • 'Coherence-ordered before',本方案中引入的新关系,仅用于定义全局seq-cst顺序,显然不强制同步(不同于Release-Acquisition操作)。

      它似乎包括了影响全球SEQ-CST秩序的所有事情,而不是"之前发生的事情"。在本例中,如果加载看不到存储写入的值,则加载将先于存储进行,这是常识。

    全局序号-CST顺序与两者一致。

请注意,在此图中,b = y.fetch_add(1, seq_cst);之前没有强烈的事件发生,因此在全局seq-cst顺序中没有必须在其之前的任何内容,因此可以将其向上移动到seq-cst顺序的开始,这就是最终发生的情况,即使它读取后面(按此顺序)操作生成的值。

这篇关于与(简单地)发生在&#39;之前相比,&#39;强烈发生在&#39;之前有什么意义呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

error when trying to run an overloaded function with float parameters.(尝试运行带有浮点参数的重载函数时出错。)
C++ lt;lt; operator overloading without friend function(没有友元函数的C++lt;lt;运算符重载)
C++ - How does the compiler decide between overloaded functions with reference types as parameter?(C++-编译器如何决定使用引用类型作为参数的重载函数?)
How can I invoke an overloaded () operator on the keyword this?(如何对关键字this调用重载()运算符?)
How do I denote a pure virtual function in a UML class diagram?(如何在UML类图中表示纯虚函数?)
MPI parallel IO in ASCII format (How do I do it?)(ASCII格式的MPI并行IO(我该怎么做?))