5

我发现了一些问题(比如这个),问什么[[carries_dependency]]是,这不是我在这里要问的。

我想知道你什么时候不应该使用它,因为我读过的所有答案都让人觉得你可以在任何地方粘贴这段代码,并且神奇地你会得到相同或更快的代码。一条评论说代码可以相同或更慢,但张贴者没有详细说明。

我想使用 this 的适当位置是在作为指针或引用的任何函数返回或参数上,并且将在调用线程中传递或返回,并且不应在回调或线程入口点上使用它。

有人可以评论我的理解并详细说明该主题,何时以及何时不使用它?

编辑:我知道这个主题有这本书,如果任何其他读者感兴趣的话;它可能包含我的答案,但我还没有机会阅读它。

4

2 回答 2

3

在现代 C++ 中,您通常不应该使用std::memory_order_consume或根本不应该使用[[carries_dependency]]。当委员会提出编译器可以实际实现的更好机制时,它们基本上已被弃用。

这希望不需要洒在所有[[carries_dependency]]地方kill_dependency

2016-06 P0371R1:暂时阻止 memory_order_consume

人们普遍认为,标准中当前对 memory_order_consume 的定义没有用。当前所有的编译器本质上都将其映射到 memory_order_acquire。困难似乎源于高实现复杂性,当前定义使用相当普遍的“依赖”定义,因此需要频繁且不方便地使用 kill_dependency 调用,以及频繁需要 [[carries_dependency] ] 注释。详细信息可以在例如P0098R0中找到。

值得注意的是,在 C++ 中x - x仍然带有依赖关系,但大多数编译器自然会破坏依赖关系并用常量替换该表达式0。但是,如果编译器可以在分支后证明一些关于值范围的内容,编译器有时也会将数据依赖关系转变为控制依赖关系。


mo_consume在刚刚升级到的现代编译器上mo_acquire,总是会发生完全积极的优化;甚至在使用的代码中也没有任何好处[[carries_dependency]],更不用说在其他代码中了。kill_dependency mo_consume


对于 POWER 和 ARM 等弱序 ISA 上的 RCU 等实际用例,这种增强mo_acquire具有潜在的显着性能成本(一个额外的障碍)。观看 Paul E. McKenney 的 CppCon 2015 演讲C++ Atomics: The Sad Story of memory_order_consume 的视频。(链接包括摘要)。

如果你想要真正的依赖排序只读性能,你必须“自己动手”,例如通过使用mo_relaxed和检查 asm 来验证它是否编译为带有依赖关系的 asm。(避免对这样的值做任何“奇怪”的事情,比如跨函数传递它。)DEC Alpha 基本上是死的,所有其他 ISA 都在 asm 中提供没有障碍的依赖排序,只要 asm 本身具有数据依赖关系。

如果您不想自己动手并过着危险的生活,那么mo_consume在应该能够工作的“简单”用例中继续使用可能不会有什么坏处;也许某些未来mo_consume的实现将具有相同的名称并以与 C++11 兼容的方式工作。


正在进行新的工作consume,例如 2018 年的http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0750r1.html

于 2019-12-10T04:58:37.490 回答
2

因为我读过的所有答案听起来都像是你可以在任何地方粘贴这段代码,并且神奇地你会得到相同或更快的代码

获得更快代码的唯一方法是该注释允许省略围栏。

因此,它可能有用的唯一情况是:

  • 您的程序在重要的频繁执行的代码中使用原子加载操作的消费排序;
  • “消费价值”不仅可以立即在本地使用,还可以传递给其他函数;
  • 目标 CPU 为消费操作提供特定保证(与该操作之前的给定栅栏一样强,仅针对该操作);
  • 编译器编写者认真对待他们的工作:他们设法将消耗值的高级语言转换为 CPU 级消耗,以从 CPU 保证中获益。

这是可能获得更快的代码的一系列必要条件。

(而 C++ 社区的最新趋势是放弃发明一种在所有情况下都安全的适当编译方案,并为用户提供一种完全不同的方式来指示编译器生成“消耗”值的代码,更明确、更天真的可翻译的 C++ 代码。)

一条评论说代码可以相同或更慢,但张贴者没有详细说明。

当然,您可以随意添加到程序上的那种注释通常不能使代码更高效!那太容易了,而且自相矛盾。

某些注释指定了对代码的约束,这是对编译器的承诺,并且您不能将其放在与代码中的保证不对应的任何地方(例如noexcept在 C++ 中,restrict在 C 中),否则它会中断以各种方式编写代码(函数中的异常会noexcept停止程序,受限指针的别名会导致有趣的错误编译和不良行为(以前在这种情况下未定义行为);然后编译器可以使用它以特定方式优化代码.

或者该注释不会以任何方式约束代码,编译器不能指望任何东西,并且该注释不会创造任何更多的优化机会

如果您在某些情况下获得更高效的代码而无需使用注释破坏程序,那么在其他情况下您可能会获得效率较低的代码。这在一般情况下是正确的,特别是对于消费语义,它对 C++ 结构的翻译施加了前面描述的约束。

我想使用 this 的适当位置是在作为指针或引用的任何函数返回或参数上,并将在调用线程中传递或返回

不,它可能有用的唯一一种情况是预期的调用函数可能会使用消耗内存顺序

于 2019-12-10T03:59:22.047 回答