Linux CPU亲和性
CPU亲合力就是指在linux系统中能够将一个或多个进程绑定到一个或多个处理器上运行。
一个进程的CPU亲合力掩码决定了该进程将在哪个或哪几个CPU上运行。在一个多处理器系统中,设置CPU亲合力的掩码可能会获得更好的性能。
一个CPU的亲合力掩码用一个cpu_set_t结构体来表示一个CPU集合,下面的几个宏分别对这个掩码集进行操作:
cpu_set_t mask; CPU_ZERO(&mask) 清空一个集合 CPU_SET(0, &mask) 将cpu0添加到集合mask中,本质为对应bit置1 CPU_CLR(0, &mask); 将cpu0从集合mask中移除,本质为对应bit清零 CPU_ISSET(1, &mask); 判断cpu1是否在集合mask中,在返回非零,不在返回0 CPU_COUNT(&mask); 返回集合set2中的CPU的个数 CPU_AND(&result, &set1, &set2); set1和set2的所有bit按位与,结果存入result CPU_OR(&result, &set1, &set2); 按位或 CPU_XOR(&result, &set1, &set2); 按位异或 CPU_EQUAL(&set1, &set2); 集合set1和集合set2相等的话,返回非零,不相等,返回0
int sched_setaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask); 函数简介 设置进程CPU亲和力 参数说明 pid: 进程ID,如果pid的值为0,则表示指定的是当前进程 cpusetsize: mask所指定的数的长度 mask: CPU集合 返回值 执行成功,返回0,执行失败,返回-1,更新errno.
int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask); 函数简介 获取进程CPU亲和力 参数说明 pid: 进程ID,如果pid的值为0,则表示指定的是当前进程 cpusetsize: mask所指定的数的长度 mask: CPU集合 返回值 执行成功,返回0,执行失败,返回-1,更新errno.
绑核成功确认方法
taskset -pc [PID]
表明当前进程在cpu0,cpu1上运行
/* cpu亲和性设置 */ #define _GNU_SOURCE /* 该宏不可缺少 */ #include <sched.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <stdio.h> #include <errno.h> #include <assert.h> int test() { int ret = 0; cpu_set_t mask; int num_cpus; int total = 0; int i, j, k; // 1.参数校验 // 2.获取当前系统的cpu核数 /* 知识补充 int sysconf(_SC_NPROCESSORS_CONF); 返回系统可以使用的核数,但是其值会包括系统中禁用的核的数目,因此该值并不代表当前系统中可用的核数 int sysconf(_SC_NPROCESSORS_ONLN); 返回值真正的代表了系统当前可用的核数 */ num_cpus = (int)sysconf(_SC_NPROCESSORS_ONLN); // 3.清空当前cpu集合 CPU_ZERO(&mask); // 4.设置需要绑定的逻辑核 /* 设计说明: a. cpu绑核是从0开始的 b. 进程绑定多个逻辑核时,现象不是在多个逻辑核之间切换,而是固定跑在一个逻辑核上,但是同时启动多个进程时,会发现每个进程跑在不同的逻辑核上 */ // 将cpu0添加到集合mask中,本质为对应bit置1 CPU_SET(0, &mask); // 将cpu1添加到集合mask中,本质为对应bit置1 CPU_SET(1, &mask); // 5.为当前进程绑核 if (sched_setaffinity(0, sizeof(mask), &mask)) { ret = -1; printf("Set CPU affinity failue, ERROR:%s\n", strerror(errno)); return ret; } // 6.计算操作 for (k = 0; k < 100000; k += 1) { for (i = 0; i < 10000; i++) { for (j = 0; j < 1000; j++) { total = (i + j) * k; } total = i * k; } } printf("num_cpus %d, total %d\n", num_cpus, total); return ret; } int main() { test(); return 0; }