首页 >后端开发 >C++ >为什么使用'memory_order_seq_cst”来设置停止标志,而使用'memory_order_relaxed”来检查它?

为什么使用'memory_order_seq_cst”来设置停止标志,而使用'memory_order_relaxed”来检查它?

Linda Hamilton
Linda Hamilton原创
2024-11-18 03:11:02374浏览

Why use `memory_order_seq_cst` for setting the stop flag but `memory_order_relaxed` for checking it?

为什么在检查 memory_order_relaxed 时使用 memory_order_seq_cst 进行停止标志设置?

在关于原子操作的讨论中,Herb Sutter 提供了一个示例用法原子,包括停止标志机制:

  • 主线程启动多个工作线程。
  • 工作线程不断检查停止标志:

    while (!stop.load(std::memory_order_relaxed))
    {
      // Do stuff.
    }
  • 主线程最终将 order=seq_cst 设置为 stop = true,然后加入worker。

Store 操作不使用relaxed 的原因

虽然 Herb 建议出于最小延迟问题而使用 memory_order_relaxed 来检查标志是可以接受的,但使用更严格的内存顺序并没有明显的性能优势,即使延迟是优先考虑的。

背后的原因不是在商店操作中使用放松仍然不清楚,可能是由于疏忽或个人偏好。

延迟注意事项

ISO C 标准不强制执行商店可见性的特定时间范围或提供有关如何影响它的指导。这些规定适用于所有原子操作,包括宽松的。但是,鼓励实现在合理的时间范围内使原子加载可以访问存储值。

实际上,具体延迟由实现决定,硬件缓存一致性机制通常允许在最佳情况下在数十纳秒内实现可见性。情况场景和接近最坏情况场景中的亚微秒间隔。

内存顺序影响

存储或加载操作的不同内存顺序不会加速实际存储时间,它们只是控制在存储仍处于待处理状态时后续操作是否可以全局可见。

本质上,更强的订单和障碍不会绝对加速事件,而是推迟其他操作,直到存储或加载完成。这对于所有现实世界的 CPU 都是如此,它们努力使存储对其他核心即时可见。

因此,增加内存顺序(例如使用 seq_cst)可确保对停止标志的更改立即对工作线程可见线程,保证快速关闭。但是,它不会影响实际的可见性延迟。

宽松检查的好处

使用 memory_order_relaxed 进行检查操作有几个优点:

  • 最小化指令级和内存级并行性瓶颈。
  • 减少指令级并行性受限架构的开销,特别是那些具有高成本障碍的架构。
  • 消除了由于分支而浪费的工作对加载结果的错误预测。

其他注意事项

Herb 正确地识别出,由于 thread.join 提供的同步,使用relaxed 作为脏标志也是可以接受的。但需要注意的是,dirty 需要原子性来防止同时写入相同的值,这在 ISO C 标准下仍然被认为是数据竞争。

综上所述,在使用 memory_order_seq_cst 设置停止标志时可以确保立即执行对于工作线程的可见性,与放松加载操作相比,这样做没有任何性能优势。 memory_order_relaxed 在指令级并行性和内存带宽利用率方面具有优势,使其成为此类场景的首选。

以上是为什么使用'memory_order_seq_cst”来设置停止标志,而使用'memory_order_relaxed”来检查它?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn