介绍
CPU 的亲和性,进程要在某个给定的 CPU 上尽量长时间地运行而不被迁移到其他处理器的倾向性,进程迁移的频率小就意味着产生的负载小。当系统将线程分配给处理器时,操作系统使用亲和性来进行操作。这意味着如果所有其他因素相同的话,它将设法在它上次运行的那个处理器上运行线程。让线程留在单个处理器上,有助于重复使用仍然在处理器的内存高速缓存中的数据。
亲和性一词是从 affinity 翻译来的,实际可以称为 CPU 绑定。
为何要手动绑定线程/进程到 CPU 核
在大数据量的数据处理过程中,我们通常需要提升处理效率和性能,一是优化算法,二是充分利用服务器的硬件资源,如 CPU 和 GPU。
平时应用程序在运行时都是由操作系统管理的。操作系统对应用进程进行调度,使其在不同的核上轮番运行。对于普通的应用程序,操作系统的默认调度机制是没有问题的。但是,当某个进程需要较高的运行效率时,就有必要考虑将其绑定到单独的核上运行,以减小由于在不同的核上调度造成的开销。
把某个进程/线程绑定到特定的 cpu 核上后,该进程就会一直在此核上运行,不会再被操作系统调度到其他核上。但绑定的这个核上还是可能会被调度运行其他应用程序的。
目前 windows 和 linux 都支持对多核 cpu 进行调度管理。软件开发在多核环境下的核心是多线程开发。这个多线程不仅代表了软件实现上多线程,要求在硬件上也采用多线程技术。
多进程和多线程在多核 CPU 上运行
在多核运行的机器上,每个 CPU 本身自己会有缓存,在缓存中存着进程使用的数据,而没有绑定 CPU 的话,进程可能会被操作系统调度到其他 CPU 上,如此 CPU cache(高速缓冲存储器)命中率就低了,也就是说调到的 CPU 缓存区中原来没有这类数据,要先把内存或硬盘的数据载入缓存。而当缓存区绑定 CPU 后,程序就会一直在指定的 CPU 执行,不会被操作系统调度到其他 CPU,性能上会有一定的提高。
另外一种使用 CPU 绑定考虑的是将关键的进程隔离开,对于部分实时进程调度优先级提高,可以将其绑定到一个指定 CPU 核上,可以保证实时进程的调度,也可以避免其他 CPU 上进程被该实时进程干扰。我们可以手动地为其分配 CPU 核,而不会过多的占用同一个 CPU,所以设置 CPU 亲和性可以使某些程序提高性能。
例如 openGauss 的 cpu_affinity 参数,将进程与 CPU 绑定,提高了 CPU cache 的命中率,从而减少内存访问损耗,提高程序的速度。
应用场景举例
将 UI 线程限制在一个 CPU,将其他实时性要求较高的线程限制在另一个 CPU。这样,当 UI 需要占用大量 CPU 时间时,就不会拖累其他实时性要求较高的线程的执行。同样可以将 UI 线程与一些优先级不高但耗时的异步运算线程设置在不同 CPU 上,避免 UI 给人卡顿的感觉。