【问题标题】:How can I evaluate performances of a lockless queue?如何评估无锁队列的性能?
【发布时间】:2011-09-27 14:49:14
【问题描述】:

我已经使用http://www.research.ibm.com/people/m/michael/ieeetpds-2004.pdf 中解释的危险指针方法实现了一个无锁队列,使用 GCC CAS 指令进行实现,pthread 本地存储用于线程本地结构。 我现在正在尝试评估我编写的代码的性能,特别是我正在尝试在此实现与使用锁(pthread 互斥锁)来保护队列的实现之间进行比较。
我在这里问这个问题是因为我尝试将它与“锁定”队列进行比较,我发现这在无锁实现方面具有更好的性能。我尝试的唯一测试是在 4 核 x86_64 机器上创建 4 个线程,在队列上执行 10.000.000 次随机操作,它比无锁版本快得多。

我想知道您是否可以建议我遵循的方法,即我必须在队列上测试什么样的操作以及我可以使用什么样的工具来查看我的无锁代码在哪里浪费时间。

我也想了解无锁队列的性能是否可能仅仅因为 4 个线程不足以看到重大改进......

谢谢

【问题讨论】:

    标签: c multithreading performance lockless


    【解决方案1】:

    第一点:无锁编程不一定能提高速度。无锁编程(如果正确完成)保证了前进。当您使用锁时,一个线程可能会在持有互斥锁时崩溃(例如,进入无限循环)。当/如果发生这种情况,没有其他线程等待该互斥体可以取得更多进展。如果该互斥锁是正常操作的核心,那么您可能很容易不得不重新启动整个过程,然后才能完成更多工作。使用无锁编程,就不会出现这种情况。无论任何一个线程发生什么,其他线程都可以向前推进1

    也就是说,是的,您希望的一件事通常是更好的性能——但要看到它,您可能需要四个以上的线程。在数十到数百个线程的某个范围内,您的无锁代码将有更好的机会显示出比基于锁的队列更好的性能。然而,要真正做好事,你不仅需要更多线程,还需要更多内核——至少根据我目前看到的情况,有四个内核和编写良好的代码,可能还不够争用无锁编程的锁以显示很多(如果有的话)性能优势。

    底线:更多线程(至少几十个)将提高无锁队列显示性能优势的机会,但只有四个内核,如果基于锁的队列仍然存在,这不足为奇跟上。如果你添加了足够多的线程和内核,那么无锁版本的胜出几乎是必然的。所需的线程和内核的确切数量很难预测,但您至少应该考虑几十个。


    1 至少对于互斥锁之类的东西。像只吃掉所有系统资源的分叉炸弹之类的东西可能会剥夺其他线程足够的资源来完成任何事情——但是像配额这样的一些注意事项通常也可以防止这种情况发生。

    【讨论】:

      【解决方案2】:

      问题实际上在于您要针对哪些工作负载进行优化。如果拥塞很少见,现代操作系统上的锁结构可能还不错。只要它们在快速路径上,它们主要使用 CAS 指令。由于这些都经过优化,因此很难用您自己的代码击败它们。

      我们自己的实现只能在拥塞的部分取得实质性的胜利。如果平均队列长度比并行攻击它的线程数长得多,那么队列上的随机操作(你的问题不是太精确)可能不会这样做。因此,您必须确保队列很短,也许通过在队列太长或太短时引入关于所选择的随机操作的偏差。然后我还会用至少两倍于内核的线程来为系统充电。这将确保等待时间(内存)不会有利于锁定版本。

      【讨论】:

      • 我知道现代操作系统锁还不错,我也知道我的问题不够精确。我刚刚尝试随机入队/出队,其中每个线程都试图在一段时间(1)内向队​​列施加压力,然后它们终止。我也知道四个核心是不够的,我只是想了解是否可以看到加速。您的回答很有用,我会尝试您的建议。
      【解决方案3】:

      在我看来,最好的方法是用锁来识别应用程序中的热点 通过分析代码。引入无锁机制并再次测量。 正如其他海报已经提到的那样,可能没有显着改善 规模较小(线程数、应用程序规模、内核数),但您可能 当你扩大系统时看到吞吐量的提高。这是因为死锁 情况已被消除,线程始终在前进。

      另一种看待无锁方案优势的方式是,对于某些人来说 范围一将系统状态与应用程序性能分离,因为有 没有内核/调度程序参与,大部分代码都是用户态,除了 对于 CAS,这是一条硬件指令。

      对于竞争激烈的锁,线程阻塞并被调度一次 获得锁,这基本上意味着它们被放置在运行结束时 队列(用于特定的优先级)。不经意间,这会将应用程序链接到系统 应用的状态和响应时间现在取决于运行队列长度。

      只要我的 2 美分。

      【讨论】:

        猜你喜欢
        • 2012-08-08
        • 2011-12-04
        • 1970-01-01
        • 1970-01-01
        • 2017-04-21
        • 2010-11-29
        • 2020-01-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多