【问题标题】:Does the C++11 standard formally define acquire, release, and consume operations?C++11 标准是否正式定义了获取、释放和消费操作?
【发布时间】:2012-05-18 13:52:25
【问题描述】:

在 C++11 标准中,第 1.10/5 节提到但没有正式定义术语 acquire operationrelease operationconsume operation。然后在第 29 节继续使用这些术语来描述某些内存排序、原子操作和内存栅栏的操作。例如,关于“秩序和一致性”的 29.3/1 指出:

memory_order_releasememory_order_acq_relmemory_order_seq_cst:存储操作在受影响的内存位置。

这种类型的语言在第 29 节中重复出现,但让我有点困扰的是,memory_order 枚举的所有含义都基于操作类型,这些操作类型本身似乎没有被标准形式化,但必须有一些共同点商定的含义,使它们作为定义有效。

换一种说法,如果我说“一个 bar 是一个翻转的 foo”,那么 barfoo 的具体含义是模棱两可的,因为这两个术语都没有正式定义。只定义了它们的相对性质。

C++11 标准或其他一些 C++11 标准委员会文件是否正式定义了 acquire operationrelease operation 等究竟是什么,或者这些只是普遍理解的术语?如果是后者,对于这些操作的含义,是否有一个很好的参考被认为是行业标准?我特别问,因为硬件内存一致性模型不是平等创建的,因此我认为必须有一些普遍同意的参考,允许那些实现编译器等的人正确地将这些操作的语义转换为本机汇编命令。

【问题讨论】:

  • 我同意 OP。该标准在逻辑上是否可解读是一个问题,但无论如何,该标准在这一特定点上异常令人困惑。
  • Jeff Preshing's blog post about release/acquire 以与 C++11 语义兼容的方式根据早/晚加载/存储所需的顺序来定义它们。我没有意识到 C++11 没有用这样的术语正式定义它们。

标签: c++ c++11 standards


【解决方案1】:

在其中一个注释中给出了一个非正式的总结定义:

A 执行释放操作会强制其他内存位置上的先前副作用对稍后对A 执行消耗或获取操作的其他线程可见。

除此之外,获取和释放操作的行为在 1.10 中完全定义,特别是它们如何促成 happens-before 关系。除了行为之外的任何定义都是无用的。

【讨论】:

  • 我猜是“非正式摘要”让我感到困扰。例如,如果您尝试将发布操作映射到给定平台的硬件指令,您必须知道语义上允许和不允许的内容,因为硬件可能不提供某些特定的“发布”操作。由于没有一对一的对应关系,因此更正式的含义可以帮助进行准确的翻译。话虽如此,我将重新阅读第 1.10 节,看看我是否无法进一步理解您所描述的行为与操作术语本身的实际使用之间的桥梁。
  • @Jason:标准侧重于行为。它不会尝试孤立地定义术语。
  • @Jason,应该注意的是,即使在英特尔技术文档中,内存顺序保证也被描述为行为顺序保证。也就是说,内存排序是由一系列指令控制的行为。对于同一平台,不同编译器的 C++ 保证顺序的实现方式可能会有所不同,而且对于不同的硬件肯定会有所不同。
  • 如果您尝试编写一些使用特定于平台的功能(如x86 cache-evicting/bypassing stores that are also weakly-ordered)并与 C++11 发布/获取语义互操作的东西,这并不是没有用的。即您正在滚动自己的发布存储,它需要与该平台的标准加载获取互操作。如果同一平台的不同编译器(或不同 ABI)可能对发布存储有不同的语义要求,则需要处理。
  • @BenVoigt:谈论使用一些平台特定功能的代码的可移植性并非无用或无意义。例如与内联汇编不同,SSE/AVX 内在函数可以提供很大的加速,并且可以跨 Windows / Linux / Mac 的不同编译器移植。如果 C++11 说了一些特定但通用的东西,比如发布存储不能与之前的加载/存储重新排序,那么编写保证在所有 x86 上工作的东西会更容易。相反,理论上你需要仔细检查所有现有的实现,即使这样你的代码也不是面向未来的。
【解决方案2】:

在快速浏览标准后,我没有看到任何正式的获取/释放语义定义,所以我的猜测是它们被假定为普遍理解的术语。

毕竟,他们无法定义一切。

这不是一个明确的参考,而是Raymond Chen has blogged about acquire/release semantics。他的帖子包括a link to Microsoft's definition of acquire and release semantics,您可能会发现它很有用。

【讨论】:

  • 您还应该考虑基本 ISO 文档,例如C 和 Unicode (10646)。
【解决方案3】:

实际上这些操作在 1.10/5-12 节中定义。

release/acquire对对应happen before关系;而release/consumedependency-ordered before 关系配对。

【讨论】:

    【解决方案4】:

    我还认为获取/释放语义本身是相当明确的;尽管它们从历史上看是更多特定于硬件的术语,而不是编程术语。

    但是,我认为第 1.10 节第 5 段和第 6 段似乎与我在其他语言标准中阅读的所有获取/释放语义定义以及 CPU 定义相匹配。

    无论如何,C++11 的一大亮点是定义了一个现代内存模型来支持并发和多线程代码。我很难相信他们没有做对:)

    【讨论】:

      猜你喜欢
      • 2013-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-18
      • 2012-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多