C ++ 11 atomic:std :: memory_order代码可移植吗?

时间:2017-07-27 16:53:36

标签: c++ multithreading c++11 atomic

在像std :: atomic :: compare_exchange这样的函数中,有像std :: memory_order_release,std :: memory_order_relaxed这样的运行时参数。 (http://en.cppreference.com/w/cpp/atomic/atomic/compare_exchange

我不确定这些内存顺序标志是否保证存在于所有类型的cpu /架构中,如果某些cpus不支持标志,此标志是否会导致崩溃或?似乎其中一些标志是为intel itanium等设计的,不确定std :: memory_order相关代码是否可移植。

你会提出一些建议吗?

3 个答案:

答案 0 :(得分:5)

一般情况下,无论您要求什么,编译器都可以免费提供最强内存保证。

在某些平台上,有足够的放松保证。并非所有平台都支持这些轻松保证。在这些平台上,编译器必须提供严格更强的保证。

所以它们是可移植的,因为当你要求特别保证的时候,合适的编译器必须提供或更好的保证。

请注意,不仅仅是关注的硬件。某些优化和重新排序可能是合法的,取决于您要求的内存顺序保证。我不知道任何依赖于它的编译器,但我不是编译器专家。

答案 1 :(得分:5)

C ++标准确实具有所谓的“独立”实现的概念,它可以支持标准库的子集。但是,它还定义了即使是独立实现必须支持的极小功能。在该列表中是<atomic>标题的完整

是的,实现必须支持这些。

但是,这并不意味着特定标志将完全执行,并且仅表示该标志所描述的内容。标志代表最小内存屏障,保证可见的特定内容。如果硬件实现没有较低级别的内存障碍,即使对于不需要它的标志,该实现也可能发出完整的内存屏障。

因此,您应该针对标准所说的内容编写代码,并让编译器对细节进行整理。如果它在平台上被证明效率低下,您可以检查装配体,看看您是否能够改善问题。

但回答你的主要问题,是的,基于原子的代码是可移植的(模数编译器错误)。

答案 2 :(得分:0)

在实践中,消费语义总是被当前的编译器所增强,因为事实证明,如果不这样做,很难安全地实现。要么:

  • 该架构在所有负载上提供获取,然后负载消耗与负载获取具有相同的作用,而负载获取与负载松弛具有相同的作用:没什么特别的(例如x86);
  • 即使依赖于依赖的访问,该架构也需要获取障碍(非常罕见,也许只有DEC Alpha):然后编译器将在消耗时使用获取障碍;
  • ISA保证对asm中的负载进行依赖排序,但是完全获取需要一个障碍。 (这就是consume试图向程序员公开的内容)。编译器应该为您提供避免使用逻辑(非疯狂)使用consumption的好处

    • 两个编译器都试图这样做,但是这很棘手,并且在某些极端情况下会失败,因为编译器的后端优化会中断(前端通常无法与其后端进行充分的通信,从而避免仅出于消耗目的); li>
    • 或者您不信任编译器,请将优化设置为零,这甚至不能保证后端隐式完成的微不足道的优化不会破坏消耗(并使性能非常差);
    • 或者编译器作者并不关心效率,或者知道他们不能在提供消耗方面做可靠的工作,因此他们提供了获取,这在语义上是正确的,但实际上效率较低,不是标准的意图。

(而且C ++的消费语义很疯狂。它是C ++最不一致的部分之一,可以告诉您很多东西。)