![Linux 内核分配给线程的不断变化的亲和力不会对整体性能产生不利影响吗?](https://linux22.com/image/57268/Linux%20%E5%86%85%E6%A0%B8%E5%88%86%E9%85%8D%E7%BB%99%E7%BA%BF%E7%A8%8B%E7%9A%84%E4%B8%8D%E6%96%AD%E5%8F%98%E5%8C%96%E7%9A%84%E4%BA%B2%E5%92%8C%E5%8A%9B%E4%B8%8D%E4%BC%9A%E5%AF%B9%E6%95%B4%E4%BD%93%E6%80%A7%E8%83%BD%E4%BA%A7%E7%94%9F%E4%B8%8D%E5%88%A9%E5%BD%B1%E5%93%8D%E5%90%97%EF%BC%9F.png)
在我的程序中,我有几个线程随进程一起启动,并一直保留到程序结束。它们在应用程序的生命周期中会遇到不同的负载,有时它们都会以 100% 的速度运行。
默认情况下,Linux 线程调度程序将非常轻率地更改多核系统上这些线程的亲和力(IMO)。当我查看图形进程监视器(gnome 中的监视器)中的弹跳图时,我不禁认为这构成了某种开销。
编辑:为了澄清,即使对于非常稳定的负载,线程也被调度在不同的核心上,即使它在图像中不可见,但有时非常清楚的是,为每个线程选择的核心经常“交换”。
这种亲和力的不断变化不会对性能产生不利影响吗?
既然如此,为什么要这样实现呢?改变亲和力有什么好处?
我的猜测是:
- 磨损均衡——不要将所有工作都放在一个核心上
- 无意 - 某些智能算法尝试根据负载优化使用情况,但碰巧开销不足以保证保持亲和力而不是改变它。
答案1
如果您要在一个核心上运行所有线程,请购买更便宜的单核心硬件。
调度程序尝试最大限度地利用所有核心。这意味着将线程分派到任何有空闲时间的核心。将线程从一个核心移动到另一个核心的成本很小,因此调度程序确实会尽力避免这种情况。但您通常不会太注意到这一点,因为不让核心闲置的好处远远大于迁移线程的成本。如果线程使用的内存多于核心本地缓存,则尤其如此:如果线程使用的内存不在核心本地缓存中,则将其迁移到另一个核心不会造成任何损失。
对工业级调度程序(例如 Linux 的调度程序)进行事后评估通常会使性能变得更差。
您显示的图表表明各个核心上的负载未满且略有变化,可能是因为您的系统作为一个整体受到当前正在执行的任务的 I/O 限制,而不是受到 CPU 功率的限制。它没有以任何方式说明线程从一个核心移动到另一个核心的频率。
答案2
这里提供的快照也取决于内核的类型(版本)。版本 2.4 的旧内核亲和力较差,导致线程的大量乒乓运动影响系统性能。从2.5开始的内核版本具有相对更好的亲和力。
在基于多核的系统上,亲和力的设置可以避免在跨核移动线程时发生缓存失效,从而提高性能。
在基于 Linux 的多核系统中,可以根据应用程序/需求的类型,使用进程的 sched_setaffinity/taskset 和线程的 pthread_setaffinity_np 来覆盖调度程序的亲和行为(自然亲和)。
内核鲨鱼似乎提供了多核系统和亲和力的更好的视觉表示。
另外,请注意顶部提供视觉支持来设置关联性(以覆盖调度程序)。