何为CPU的亲和性
CPU的亲和性,进程要在某个给定的 CPU 上尽量长时间地运行而不被迁移到其他处理器的倾向性,进程迁移的频率小就意味着产生的负载小。亲和性一词是从affinity翻译来的,实际可以称为CPU绑定。
在多核运行的机器上,每个CPU本身自己会有缓存,在缓存中存着进程使用的数据,而没有绑定CPU的话,进程可能会被操作系统调度到其他CPU上,如此CPU cache(高速缓冲存储器)命中率就低了,也就是说调到的CPU缓存区没有这类数据,要先把内存或硬盘的数据载入缓存。而当缓存区绑定CPU后,程序就会一直在指定的CPU执行,不会被操作系统调度到其他CPU,性能上会有一定的提高。
另外一种使用CPU绑定考虑的是将关键的进程隔离开,对于部分实时进程调度优先级提高,可以将其绑定到一个指定CPU核上,可以保证实时进程的调度,也可以避免其他CPU上进程被该实时进程干扰。
我们可以手动地为其分配CPU核,而不会过多的占用同一个CPU,所以设置CPU亲和性可以使某些程序提高性能。
Linux操作系统的CPU亲和性特征
操作系统部分Linux的调度程序同时提供”软CPU亲和性”和”硬CPU亲和性”
软亲和性:进程要在指定的 CPU 上尽量长时间地运行而不被迁移到其他CPU。
Linux 内核进程调度器天生就具有被称为 软 CPU 亲和性(affinity) 的特性,因此linux通过这种软的亲和性试图使某进程尽可能在同一个CPU上运行。
硬亲和性:将进程或者线程绑定到某一个指定的cpu核运行
虽然Linux尽力通过一种软的亲和性试图使进程尽量在同一个处理器上运行,但它也允许用户强制指定进程无论如何都必须在指定的处理器上运行。
硬亲和性使用场景
硬亲和性场景:需要保持高CPU缓存命中率时、需要测试复杂的应用程序时。
保持高CPU缓存命中率:如果一个给定的进程迁移到其他地方去了,那么它就失去了利用 CPU 缓存的优势。实际上,如果正在使用的 CPU 需要为自己缓存一些特殊的数据,那么所有其他 CPU 都会使这些数据在自己的缓存中失效。因此,如果有多个线程都需要相同的数据,那么将这些线程绑定到一个特定的 CPU 上是非常有意义的,这样就确保它们可以访问相同的缓存数据(或者至少可以提高缓存的命中率)。否则,这些线程可能会在不同的 CPU 上执行,这样会频繁地使其他缓存项失效。
测试复杂的应用程序:考虑一个需要进行线性可伸缩性测试的应用程序。有些产品声明可以在使用更多硬件时执行得更好。 我们不用购买多台机器(为每种处理器配置都购买一台机器),而是可以:1.购买一台多处理器的机器;2.不断增加分配的处理器;3.测量每秒的事务数;4.评估结果的可伸缩性。
在Linux操作系统中修改CPU亲和性的手段
在Linux内核中,所有的进程都有一个相关的数据结构,称为 task_struct。这个结构非常重要,其中与 亲和性(affinity)相关度最高的是 cpus_allowed 位掩码。这个位掩码由 n 位组成,与系统中的 n 个逻辑处理器对应。 具有 4 个物理 CPU 的系统可以有 4 位。如果这些 CPU 都启用了超线程,那么这个系统就有8个位掩码。 如果为给定的进程设置了给定的位,那么这个进程就可以在相关的 CPU 上运行。因此,如果一个进程可以在任何 CPU 上运行,并且能够根据需要在处理器之间进行迁移,那么位掩码就全是 1。这是 Linux 中进程的预设状态!
Linux 内核 API 提供了一些方法,让用户可以修改位掩码或查看当前的位掩码,控制和绑定进程在特定的CPU:
sched_set_affinity() (用来修改位掩码)
sched_get_affinity() (用来查看当前的位掩码)
cpus_allowed(用于控制进程可以在哪里处理器上运行)
sched_setaffinity(用于某个进程绑定到一个特定的CPU)
文章阅读知识点:
物理CPU:机器上实际安装的CPU个数,比如说你的主板上安装了一块8核CPU,那么物理CPU个数就是1个,所以物理CPU个数就是主板上安装的CPU个数。
逻辑CPU:一般情况,我们认为一颗CPU可以有多个核,加上intel的超线程技术(HT), 可以在逻辑上再分一倍数量的CPU core出来。
超线程技术(Hyper-Threading):就是利用特殊的硬件指令,把单个物理CPU模拟成两个CPU(逻辑CPU),实现多线程。我们常听到的双核四线程/四核八线程指的就是支持超线程技术的CPU。
领取专属 10元无门槛券
私享最新 技术干货