多核系统上Linux线程调度的差异?

多核系统上Linux线程调度的差异?,linux,multithreading,scheduling,latency,rhel,Linux,Multithreading,Scheduling,Latency,Rhel,我们有几个对延迟敏感的“管道”式程序,当在一个Linux内核上运行时,与另一个Linux内核相比,它们的性能下降是可以测量的。特别是,我们看到2.6.9 CentOS 4.x(RHEL4)内核的性能更好,而CentOS 5.x(RHEL5)的2.6.18内核的性能更差 所谓“管道”程序,我指的是有多个线程的程序。多线程处理共享数据。在每个线程之间,都有一个队列。因此线程A获取数据,推入Qab,线程B从Qab提取数据,进行一些处理,然后推入Qbc,线程C从Qbc提取数据,等等。初始数据来自网络(由

我们有几个对延迟敏感的“管道”式程序,当在一个Linux内核上运行时,与另一个Linux内核相比,它们的性能下降是可以测量的。特别是,我们看到2.6.9 CentOS 4.x(RHEL4)内核的性能更好,而CentOS 5.x(RHEL5)的2.6.18内核的性能更差

所谓“管道”程序,我指的是有多个线程的程序。多线程处理共享数据。在每个线程之间,都有一个队列。因此线程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就更快了——一般来说,但在我的队列测试和实际生产运行中尤其如此。

Hmm。。如果从生产者-消费者队列执行pop()操作所花费的时间对应用程序的整体性能产生了重大影响,我建议您的线程/工作流的结构不是最优的。除非队列上存在大量争用,否则如果任何现代操作系统上的任何P-C队列推送/弹出都需要超过1µS左右的时间,我会感到惊讶,即使队列以经典的“计算机科学117-如何使用三个信号量创建有界P-C队列”的方式使用内核锁


您能否将工作最少的线程的功能吸收到工作最多的线程中,从而减少流经系统的每个总体工作项的推送/弹出次数?

Linux调度程序多年来一直是一个激烈的变化和争论领域。您可能想尝试一个最新的内核并尝试一下。是的,你可能需要自己编译,这对你有好处。你也可以(当你有较新的内核)想考虑把不同的进程放在不同的容器中,把其他的东西放在另一个容器中,看看它是否有用。
至于其他随机操作,您可以提高各种进程的优先级,添加实时语义(注意,具有实时权限的错误程序可能会使系统的其余部分陷入饥饿状态)。

排队列操作只会在较慢的情况下(即较新的RHEL5内核)对性能产生影响。根据我的实验,我对这一点的最好解释是,不同的线程被安排在内核上,这样就失去了缓存的好处。我忘了提到,我的机器有双四核CPU包。直观地说,如果在两个CPU包中调度的两个线程之间存在共享队列,那么性能将非常糟糕。但是,这只是一个猜测,因此提出了一个问题。:)我懂了。现在您提到它,我确实记得有一次故意填充线程间comms对象,以确保两个实例不能位于同一缓存线上。我想如果涉及到两个独立的包,情况会变得更糟:(是的-我不知道线程间类/struct/什么的中有多少数据,但是你能在启动时创建一个数据池,确保它们的大小(比如4k)和页面边界上吗?这应该可以减少缓存刷新,因为没有两个内核必须在同一个数据页上运行。你也可以使用
posix_memalign
,将缓存线大小传递为alignment哦,对-不知道“memalign”-大部分是Windows开发人员&因此我必须“手动”添加额外的字节缓冲区,并对它们进行一次评估,以确保编译器不会优化它们:)而不将线程绑定到内核(即taskset/sched_setaffinity()),在主线2.6.39内核(来自elrepo)中,延迟会显著恶化。看来,无论做了什么更改,都对我们的程序类型不利。我真正想问的是,这些更改是什么?除了成为内核专家,还有什么方法可以从概念上理解调度程序的更改吗?@Matt:AFAIK您的最佳选择是浏览内核新手更改列表进行讨论性能和调度程序的调整,并准备测试大量内核。