前言
现在计算机上的CPU大多都是多核的,有4核甚至是8核的。但是一个计算机启动之后其进程数是远远多于CPU核数的,因为操作系统会给自动调度这些进程在CPU核上轮流运行。但是对于应用程序或者进程,其性能要求较高时,可能有必要绑定该进程到指定的CPU核来运行,避免调度带来的额外开销。我自己也是因为最近的项目上有需要进程运行在指定的CPU核上的要求,所以了解了一下这项技术,并且将过程和总结记录于此。
CPU亲和性
在学习这项新技术之前,我们先来了解一下什么是CPU亲和性?所谓亲和性,就是把进程在指定的 CPU 上尽量长时间地运行而不被迁移到其他处理器,也称为CPU关联性;再简单的点的描述就将制定的进程或线程绑定到相应的cpu上;在多核运行的机器上,每个CPU本身自己会有缓存,缓存着进程使用的信息,而进程可能会被OS调度到其他CPU上,如此,CPU cache命中率就低了,当绑定CPU后,程序就会一直在指定的cpu跑,不会由操作系统调度到其他CPU上,性能有一定的提高。
预备知识
在编写测试程序之前,我们先来了解一下CPU相关的宏和函数。
1.首先要想使用CPU系列函数及相关的宏,需要声明下面的宏,以告诉编译器启用这些函数
#define _GNU_SOURCE
2.声明一个cpu_set_t,然后用 CPU_ZERO()宏来初始化数据:
cpu_set_t mask;
CPU_ZERO(&mask);
3.再下来就是要指定绑定的CPU核心,用CPU_SET()宏来指定,例如:
CPU_SET(1, &mask);//绑定CPU核心1
4.下面这个函数是进程绑定CPU核心最关键函数,也是实际绑定CPU核的操作。其原型即参数说明如下:
int sched_setaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask);
该函数设置进程为pid的这个进程,让它运行在mask所设定的CPU上.如果pid的值为0,则表示指定的是当前进程,使当前进程运行在mask所设定的那些CPU上.第二个参数cpusetsize是mask所指定的数的长度.通常设定为sizeof(cpu_set_t).如果当前pid所指定的进程此时没有运行在mask所指定的任意一个CPU上