处理器的亲和性
软亲和性(affinity) 意味着进程并不会在处理器之间频繁迁移,而 硬亲和性(affinity) 则意味着进程需要在您指定的处理器上运行。
通常 Linux 内核都可以很好地对进程进行调度,在应该运行的地方运行进程(这就是说,在可用的处理器上运行并获得很好的整体性能)。内核包含了一些用来检测 CPU
之间任务负载迁移的算法,可以启用进程迁移来降低繁忙的处理器的压力。
一般情况下,在应用程序中只需使用缺省的调度器行为。然而,您可能会希望修改这些缺省行为以实现性能的优化。
在 Linux 内核中,所有的进程都有一个相关的数据结构,称为 task_struct
。这个结构非常重要,原因有很多;其中与 亲和性(affinity)相关度最高的是 cpus_allowed
位掩码。这个位掩码由 n 位组成,与系统中的 n 个逻辑处理器一一对应。 具有 4 个物理 CPU 的系统可以有 4 位。如果这些 CPU 都启用了超线程,那么这个系统就有一个 8 位的位掩码。
如果为给定的进程设置了给定的位,那么这个进程就可以在相关的 CPU 上运行。因此,如果一个进程可以在任何 CPU 上运行,并且能够根据需要在处理器之间进行迁移,那么位掩码就全是 1。实际上,这就是 Linux 中进程的缺省状态。
Linux 内核 API 提供了一些方法,让用户可以修改位掩码或查看当前的位掩码:
sched_setaffinity()
(用来修改位掩码)sched_getaffinity()
(用来查看当前的位掩码)
注意,cpu_affinity
会被传递给子线程,因此应该适当地调用 sched_setaffinity
。
相关函数包含在/usr/include/sched.h头文件中,并且需要定义#define __USE_GNU为了使用其中的一些宏。
1 #include<stdlib.h> 2 #include<stdio.h> 3 #include<sys/types.h> 4 #include<sys/sysinfo.h> 5 #include<unistd.h> 6 #include<sched.h> 7 #include<ctype.h> 8 #include<string.h> 9 #define __USE_GNU 10 11 inline int set_cpu(int i) 12 { 13 int cpu_nums = sysconf(_SC_NPROCESSORS_CONF);//获取cpu个数 14 cpu_set_t mask; 15 16 CPU_ZERO(&mask); 17 printf("system has %i processor(s). ", cpu_nums); 18 19 if(i < cpu_nums) 20 { 21 CPU_SET(i,&mask); 22 if(-1 == sched_setaffinity(gettid(),sizeof(&mask),&mask)) 23 { 24 printf("warning: could not set CPU affinity, continuing... "); 25 return -1; 26 } 27 } 28 return 0; 29 } 30 31 32 int main(int argc, char* argv[]) 33 { 34 35 int created_thread = 0; 36 int myid; 37 int i; 38 int j = 0; 39 cpu_set_t get; 40 41 if (argc != 2) 42 { 43 printf("usage : ./cpu num "); 44 exit(1); 45 } 46 myid = atoi(argv[1]); 47 48 set_cpu(myid) 49 int num = sysconf(_SC_NPROCESSORS_CONF); 50 while (1) 51 { 52 CPU_ZERO(&get); 53 if (sched_getaffinity(0, sizeof(get), &get) == -1) 54 { 55 printf("warning: cound not get cpu affinity, continuing... "); 56 } 57 for (i = 0; i < num; i++) 58 { 59 if (CPU_ISSET(i, &get)) 60 { 61 printf("this process %d is running processor : %d ",getpid(), i); 62 } 63 } 64 } 65 return 0; 66 }
参考文献