gpt4 book ai didi

c++ - 在 Folly 的无锁 SPSC 队列中使用 std::memory_order_consume

转载 作者:可可西里 更新时间:2023-11-01 17:57:29 37 4
gpt4 key购买 nike

在试图理解如何处理无锁代码的过程中,我尝试编写一个单一消费者/单一生产者无锁队列。一如既往,我检查了论文、文章和代码,特别是考虑到这是一个有点微妙的主题。

所以,我在 Folly 库中偶然发现了这个数据结构的实现,可以在这里找到: https://github.com/facebook/folly/blob/master/folly/ProducerConsumerQueue.h

就像我看到的每个无锁队列一样,这个队列似乎使用循环缓冲区,所以我们有两个 std::atomic<unsigned int>变量:readIndex_writeIndex_ . readIndex_指示我们将阅读的下一个索引,以及 writeIndex_下一个我们将写的。看起来很简单。

因此,乍一看,实现似乎很干净而且非常简单,但我发现有一点很麻烦。事实上,一些函数像 isEmpty() , isFull()guessSize()正在使用 std::memory_order_consume检索索引的值。

公平地说,我真的不知道它们的用途是什么。别误会,我知道 std::memory_order_consume 的用法在通过原子指针进行依赖的经典情况下,但在这里,我们似乎没有任何依赖!我们只是得到索引,无符号整数,我们不创建依赖关系。在这种情况下对我来说,std::memory_order_relaxed是等价的。

但是,我不相信自己比设计此代码的人更能理解内存顺序,因此我为什么要在这里问这个问题。有什么我遗漏或误解的吗?

提前感谢您的回答!

最佳答案

几个月前我也有同样的想法,所以我提交了this pull request回到 10 月,建议他们将 std::memory_order_consume 加载更改为 std::memory_order_relaxed 因为消费根本没有意义,因为没有可以携带的依赖项使用这些函数从一个线程到另一个线程。它最终引发了一些讨论,这些讨论揭示了 isEmpty()isFull()sizeGuess 的可能用例如下:

//Consumer    
while( queue.isEmpty() ) {} // spin until producer writes
use_queue(); // At this point, the writes from producer _should_ be visible

这就是为什么他们解释说 std::memory_order_relaxed 不合适而 std::memory_order_consume 合适。然而,这只是因为 std::memory_order_consume 在我所知道的所有编译器上被提升为 std::memory_order_acquire。因此,虽然 std::memory_order_consume 可能看起来提供了正确的同步,但将其留在代码中并假设它将保持正确是相当误导的,尤其是如果 std::memory_order_consume 将按预期实现。上述用例无法在较弱的架构上运行,因为不会生成适当的同步。

他们真正需要的是让这些加载 std::memory_order_acquire 使其按预期工作,这就是我提交 this other pull request 的原因几天前。或者,他们可以将获取负载从循环中取出并在末尾使用栅栏:

//Consumer    
while( queue.isEmpty() ) {} // spin until producer writes using relaxed loads
std::atomic_thread_fence(std::memory_order_acquire);
use_queue(); // At this point, the writes from producer _should_ be visible

无论哪种方式,std::memory_order_consume 在这里都被错误地使用了。

关于c++ - 在 Folly 的无锁 SPSC 队列中使用 std::memory_order_consume,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36159251/

37 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com