如何评估无锁队列的性能?

时间:2011-09-27 14:49:15

标签: c multithreading performance lockless

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

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

我还想了解,如果4个线程不足以看到重大改进,那么无锁队列的性能是否可能更差......

由于

3 个答案:

答案 0 :(得分:3)

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

那就是说,是的,你希望的事情之一往往是更好的表现 - 但要看到它,你可能需要超过四个线程。在数十到数百个线程范围内的某个位置可以使您的无锁代码比基于锁的队列显示出更好的性能。然而,要真正做很多好事,你不仅需要更多线程,还需要更多内核 - 至少基于我目前所见,具有四个内核和编写良好的代码,不太可能对无锁编程的锁争用,以显示很多(如果有的话)性能优势。

结论:更多线程(至少几十个)将提高无锁队列显示性能优势的机会,但只有四个内核,如果基于锁的队列仍然不会令人惊讶跟上。如果你添加了足够的线程和核心,那么无锁版本几乎是不可避免的。必要的线程和核心的确切数量很难预测,但你应该至少考虑几十个。


1 至少对于像互斥体这样的东西。像一个只占用所有系统资源的分叉炸弹之类的东西可能会剥夺其他线程足够的资源来完成任何事情 - 但是一些像配额这样的事情通常也会阻止它。

答案 1 :(得分:1)

问题实际上是您正在优化的工作负载。如果拥挤很少,现代操作系统上的锁定结构可能不会太糟糕。只要它们在快速路径上,它们主要使用引擎盖下的CAS指令。由于这些都已经过优化,因此很难用自己的代码打败它们。

我们自己的实施只能为拥挤的部分赢得大幅度。如果平均队列长度远远大于并行攻击它的线程数,那么对队列进行随机操作(你的问题不是太精确)可能不会这样做。因此,您必须确保队列很短,可能是通过引入对队列太长或太短时所选择的随机操作的偏见。然后我还会给系统充电至少两倍于核心的线程。这将确保等待时间(对于内存)不会有利于锁定版本。

答案 2 :(得分:1)

我认为最好的方法是使用锁定识别应用程序中的热点 通过分析代码。介绍无锁机制并再次测量它。 正如其他海报所述,可能没有明显改善 在较低的规模(线程数,应用程序规模,核心数),但你可能 在扩展系统时看到吞吐量的改进。这是因为死锁 情况已经消除,线索总是在不断进步。

使用无锁方案查看优势的另一种方法是对某些人 范围之一将系统状态与应用程序性能分离,因为那里 没有内核/调度程序参与,大部分代码都是userland,除了 CAS是一个hw指令。

对于严重争用的锁,线程会阻塞并安排一次 获得锁定,这基本上意味着它们被放置在运行结束时 queue(对于特定的prio级别)。无意中将应用程序链接到系统 应用程序的状态和响应时间现在取决于运行队列长度。

只需2美分。