2011-05-24 179 views
6

我们有几个延迟敏感的“管道”风格的程序,在一个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的速度更快 - 一般来说,但特别是在我的队列测试和实际生产运行中。

回答

1

嗯..如果生产者 - 消费者队列中的pop()操作花费的时间对应用程序的整体性能产生了重大影响,我建议您的线程/ workFlow的结构不是最佳的,某处。除非在队列中存在大量的争用,否则即使队列在经典的“计算机科学”117中使用内核锁,任何现代操作系统上的PC队列推送/弹出都会超过μS左右,我都会感到惊讶 - 如何用三种信号灯的方式制作一个有限的PC队列。

你能只吸收线/秒即做最少的功为那些做的大部分功能,因此减少流经你的系统每总体工作项目推/弹出的号码吗?

+0

出队操作仅对较慢的情况(即较新的RHEL5内核)产生性能影响。根据我的实验,我对此的最佳猜测解释是不同的线程在核心上进行调度,从而失去缓存优势。我忘了提及,我的机器具有双核四核CPU封装。直观地说,如果在两个CPU _packages_中调度的两个线程之间存在共享队列,那么性能将会很糟糕。但是,这只是一个猜测,因此是一个问题。 :) – Matt 2011-05-24 17:27:17

+0

我明白了。现在你提到它了,我记得有一次故意填充一个线程间通信对象,以确保两个实例不能位于同一个缓存线上。如果涉及到两个离散包,我认为事情会变得更加严峻:( – 2011-05-24 17:33:10

+0

是的 - 我不知道有多少数据在您的线程间类/ struct/whatever中,但是您可以在启动时创建它们的池,以确保它们的大小是4k还是在页面边界上?这应该减少缓存刷新,因为没有两个内核会在同一页数据上运行。 – 2011-05-24 17:41:49

1

Linux调度程序多年来一直是一个变化和争论的热点领域。你可能想尝试一个非常新的内核,并给出一个去。是的,你可能必须自己编译它 - 这对你有好处。你也可以(当你拥有较新的内核时)想要考虑将不同的进程放在不同的容器中,并将所有其他进程放入另一个容器中,看看是否有帮助。

就其他随机事件而言,您可以提高各种流程的优先级,添加实时语义(注意,具有实时特权的错误诊断程序会使系统的其他部分瘫痪)。

+0

没有将线程绑定到内核(即taskset/sched_setaffinity()),在mainline 2.6.39内核(来自elrepo)中,延迟会显着恶化。看来无论做什么样的改变,这对我们的程序类型都是不利的。我的问题真正的内容是,这些变化是什么?而且,在成为内核专家之后,是否有办法从概念层面理解调度程序的变化? – Matt 2011-05-30 21:58:37

+0

@Matt:AFAIK你最好的选择是通过内核新手更改列表http://kernelnewbies.org/Linux26Changes来讨论性能和调度程序调整,并准备测试很多内核。 – 2011-05-31 17:55:37