我们有几个延迟敏感的“管道”风格的程序,在一个Linux内核上运行时,其性能会有明显的下降。尤其是,我们发现2.6.9 CentOS 4.x(RHEL4)内核的性能更好,而CentOS 5.x(RHEL5)2.6.18内核的性能更差。多核系统上的Linux线程调度差异?
“管道”程序,我的意思是一个有多个线程。多线程处理共享数据。每个线程之间都有一个队列。因此,线程A获取数据,将数据推入Qab,线程B从Qab中抽取,执行一些处理,然后推入Qbc,线程C从Qbc中抽取等等。初始数据来自网络(由第三方生成)。
我们基本上测量从接收数据到最后一个线程执行任务的时间。在我们的应用程序中,当从CentOS 4移至CentOS 5时,我们看到从20微秒到50微秒的增加。
我已经使用了几种分析我们应用程序的方法,并确定在CentOS 5上增加的延迟来自队列操作(特别是弹出)。
但是,通过使用taskset将程序绑定到可用内核的子集,我可以提高CentOS 5的性能(与CentOS 4相同)。
因此,在CentOS 4和5之间,引起线程调度不同(对于我们的应用程序来说这是不理想的)的一些改变(可能是内核)。
虽然我可以使用taskset(或通过sched_setaffinity()在代码中)“解决”这个问题,但我的首选是不必这样做。我希望有某种内核可调参数(或者可能是可调参数的集合),其默认值在版本之间进行了更改。
任何人都有这方面的经验?也许还有一些地方需要调查?
更新:在这种特殊情况下,通过来自服务器供应商(Dell)的BIOS更新解决了此问题。我在这一张上拉了一会儿头发。直到我回到基础,并检查了我的供应商的BIOS更新。可疑的是,其中一项更新表示“在最佳性能模式下提高性能”。一旦我升级了BIOS,CentOS 5的速度更快 - 一般来说,但特别是在我的队列测试和实际生产运行中。
出队操作仅对较慢的情况(即较新的RHEL5内核)产生性能影响。根据我的实验,我对此的最佳猜测解释是不同的线程在核心上进行调度,从而失去缓存优势。我忘了提及,我的机器具有双核四核CPU封装。直观地说,如果在两个CPU _packages_中调度的两个线程之间存在共享队列,那么性能将会很糟糕。但是,这只是一个猜测,因此是一个问题。 :) – Matt 2011-05-24 17:27:17
我明白了。现在你提到它了,我记得有一次故意填充一个线程间通信对象,以确保两个实例不能位于同一个缓存线上。如果涉及到两个离散包,我认为事情会变得更加严峻:( – 2011-05-24 17:33:10
是的 - 我不知道有多少数据在您的线程间类/ struct/whatever中,但是您可以在启动时创建它们的池,以确保它们的大小是4k还是在页面边界上?这应该减少缓存刷新,因为没有两个内核会在同一页数据上运行。 – 2011-05-24 17:41:49