在Linux系统中,进程的调度切换是由内核自动完成的,在多核CPU上,进程有可能在不同的CPU核上来回切换执行,这对CPU的缓存不是很有利。为什么呢?看一张 Intel i5 CPU 的缓存简单示意图:

在多核CPU结构中,每个核心有各自的L1、L2缓存,而L3缓存是共用的。如果一个进程在核心间来回切换,各个核心的缓存命中率就会受到影响。相反如果进程不管如何调度,都始终可以在一个核心上执行,那么其数据的L1、L2 缓存的命中率可以显著提高。

下面会介绍taskset命令,以及sched_setaffinity系统调用,两者均可以指定进程运行的CPU实例。

1、进程绑定cpu情况查看

1.1)pidstat命令:

直接输入pidstat

查看某一个进程:

 

1.2)top命令:

  • top命令
  • 输入f,进入界面,列出来top命令的所有列
  • 上下键移动,空格键选中要显示的列
  • 左右键选中,然后上下移动可以排序

2、taskset命令

taskset是LINUX提供的一个命令,他可以让某个程序运行在某个(或)某些CPU上。所谓cpu绑定,其实就是对进程或线程设置相应的cpu亲和力(affinity),确保进程或线程只会在设置了相应标志位的cpu上运行,进而提高应用对cpu的使用效率。

1)查看进程的cpu亲和力:

$ taskset -p 14795
pid 14795's current affinity mask: 3
$ taskset -cp 14795
pid 14795's current affinity list: 0,1

示例中,查看进程14795的cpu亲和力,使用-p选项指定需要查询的进程号,默认打印的是一个十六进制数,如果使用-cp选项打印的是一个cpu列表,表示相应的cpu核。3的二进制形式是0011,相应的第0位和第1位都是1,对应了-cp打印的0和1,表示14795进程只能运行在cpu的第0个核和第1个核。

2)将进程绑定到指定cpu:

$ taskset -p 0x1 14795
pid 14795's current affinity mask: 3
pid 14795's new affinity mask: 1
或

$ taskset -cp 0 14795
pid 14795's current affinity list: 0,1
pid 14795's new affinity list: 0

示例中,通过taskset命令重新设置了进程14795的cpu亲和力,前后2种方式设置效果一样,都表示进程14795只能运行在cpu的第0个核。因为-p指定的0x01二进制形式为0001,第0位是1,表示第0个cpu核。-cp直接指定了0,也表示第0个cpu核。

3)taskset命令启动进程,并指定应用运行的cpu

$ taskset 0x1 sleep 10000 &
[2] 14925
$ taskset -p 14925
pid 14925's current affinity mask: 1
$ taskset -cp 14925
pid 14925's current affinity list: 0

示例中,通过taskset启动应用(使用sleep命令模拟应用),并设置相应的cpu亲和力,即进程14925只能运行在cpu的第0个核。启动程序后查看进程的cpu亲和力,和启动时设置的相同。

3、sched_setaffinity:

除了通过taskset命令实现cpu绑定,很多语言都提供了相应的api实现cpu绑定功能,例如c的sched_setaffinity和sched_getaffinity,python 3的os.sched_setaffinity和os.sched_getaffinity。

/* Short test program to test sched_setaffinity
* (which sets the affinity of processes to processors).
* Compile: gcc sched_setaffinity_test.c
*              -o sched_setaffinity_test -lm
* Usage: ./sched_setaffinity_test
*
* Open a "top"-window at the same time and see all the work
* being done on CPU 0 first and after a short wait on CPU 1.
* Repeat with different numbers to make sure, it is not a
* coincidence.
*/
 
#include <stdio.h>
#include <math.h>
#include <sched.h>
 
double waste_time(long n)
{
    double res = 0;
    long i = 0;
    while(i <n * 200000) {
        i++;
        res += sqrt (i);
    }
    return res;
}
 
int main(int argc, char **argv)
{
    unsigned long mask = 1; /* processor 0 */
 
    /* bind process to processor 0 */
    if (sched_setaffinity(0, sizeof(mask), &mask) <0) {
        perror("sched_setaffinity");
    }
 
    /* waste some time so the work is visible with "top" */
    printf ("result: %f\n", waste_time (2000));
 
    mask = 2; /* process switches to processor 1 now */
    if (sched_setaffinity(0, sizeof(mask), &mask) <0) {
        perror("sched_setaffinity");
    }
 
    /* waste some more time to see the processor switch */
    printf ("result: %f\n", waste_time (2000));
}

 https://reborncodinglife.com/2018/05/31/how-to-binding-cpu-on-linux/

https://www.cnblogs.com/liuhao/archive/2012/06/21/2558069.html

Logo

更多推荐