一.CPU affinity
linux中将某个进程或者线程绑定到特定的一个或者多个cpu上执行。
二.为什么需要CPU affinity
cache性能的提升,多个进程不断交替地在某个cpu上执行,导致缓存无效。
多线程程序运行于某个cpu,每个线程轮流占据cpu资源,共享cache,导致cache性能下降。
专有程序的实时性,当把专有进程保定与一个核,其余所有进程绑定与剩余的核,保证了专有程序的性能。
三.Linux cpu affinity 调用函数
a.进程cpu affinity设置
int sched_setaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask);
int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask);
第一个函数设置进程号为pid的cpu亲和性
第二个函数获取进程号为pid的cpu亲和性
b.线程cpu affinity设置
int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize, onst cpu_set_t *cpuset);
int pthread_getaffinity_np(pthread_t thread, size_t cpusetsize, cpu_set_t *cpuset);
第一个函数设置线程号为thread的cpu 亲和性
第二个函数获取线程号为thread的cpu 亲和性
四.例子
1. 进程cpu affinity设置 task_affi.c:
#define _GNU_SOURCE #include <stdio.h> #include <math.h> #include <unistd.h> #include <sched.h> #include <pthread.h> #include <assert.h> /*waste some time but ,ocuppy the cup*/ static waste_time(long n) { double res = 0; long i = 0; while(i <n * 200000) { i++; res += sqrt(i); } return res; } int main() { cpu_set_t cpuset; int ret, j, num_cpus, core; pid_t pid; pid = getpid(); num_cpus = sysconf(_SC_NPROCESSORS_CONF);/*get the cpu nums*/ assert(num_cpus > 0); printf("cpu num:%d\n", num_cpus); core = 0 % num_cpus; CPU_ZERO(&cpuset); CPU_SET(core, &cpuset); ret = sched_setaffinity(pid, sizeof(cpu_set_t), &cpuset); assert(ret == 0); ret = sched_getaffinity(pid, sizeof(cpu_set_t), &cpuset); assert(ret == 0); for (j = 0; j < CPU_SETSIZE; j++) if (CPU_ISSET(j, &cpuset)) printf("after set program bind on CPU %d\n", j); printf ("core %d result: %f\n", core, waste_time (5000)); core = 1%num_cpus; CPU_ZERO(&cpuset); CPU_SET(core, &cpuset); ret = sched_setaffinity(pid, sizeof(cpu_set_t), &cpuset); assert(ret == 0); ret = sched_getaffinity(pid, sizeof(cpu_set_t), &cpuset); assert(ret == 0); for (j = 0; j < CPU_SETSIZE; j++) if (CPU_ISSET(j, &cpuset)) printf("after set program bind on CPU %d\n", j); printf ("core %d result: %f\n", core, waste_time (5000)); return 0; }
gcc 编译:
gcc task_affi.c -lm
2. 线程cpu affinity设置 thread_affi.c:
#define _GNU_SOURCE #include <stdio.h> #include <unistd.h> #include <sched.h> #include <pthread.h> #include <assert.h> static int cpu_nums; static waste_time(long n) { double res = 0; long i = 0; while(i <n * 200000) { i++; res += sqrt(i); } return res; } void *function1(void *argc) { pthread_t thread_id; int ret, j, core; cpu_set_t cpuset; thread_id = pthread_self(); printf("porgran pid:%u, the function1 pthread id is %lu\n",getpid(), thread_id); core = 0 % cpu_nums; CPU_ZERO(&cpuset); CPU_SET(core, &cpuset); ret = pthread_setaffinity_np(thread_id, sizeof(cpu_set_t), &cpuset); assert(ret == 0); /* Check the actual affinity mask assigned to the thread */ ret = pthread_getaffinity_np(thread_id, sizeof(cpu_set_t), &cpuset); assert(ret == 0); printf("thread_id:%lu set the cpu:", thread_id); for (j = 0; j < CPU_SETSIZE; j++) if (CPU_ISSET(j, &cpuset)) printf(" CPU %d\n\n", j); printf ("the function1 pthread id is %lu, bind core %d \n", thread_id, core ); printf("the function1 result: %f \n\n",waste_time (5000) ); return 0; } void *function2(void *argc) { pthread_t thread_id; int ret, j, core; cpu_set_t cpuset; thread_id = pthread_self(); printf("porgran pid:%u, the function2 pthread id is %lu\n",getpid(), thread_id); sleep(5); core = 1 % cpu_nums; CPU_ZERO(&cpuset); CPU_SET(core, &cpuset); ret = pthread_setaffinity_np(thread_id, sizeof(cpu_set_t), &cpuset); assert(ret == 0); /* Check the actual affinity mask assigned to the thread */ ret = pthread_getaffinity_np(thread_id, sizeof(cpu_set_t), &cpuset); assert(ret == 0); printf("thread_id:%lu set the cup:\n", thread_id); for (j = 0; j < CPU_SETSIZE; j++) if (CPU_ISSET(j, &cpuset)) printf(" CPU %d\n", j); printf ("the function2 pthread id is %lu, bind core %d \n", thread_id, core); printf ("the function2 result is: %f\n",waste_time (5000) ); return 0; } int main() { pthread_t thread_id[2]; int ret, j, core; pthread_t main_thread_id; cpu_set_t cpuset; main_thread_id = pthread_self(); cpu_nums = sysconf(_SC_NPROCESSORS_CONF); assert(cpu_nums > 0); printf("cpu num:%d\n", cpu_nums); core = 0 % cpu_nums; printf("porgran pid:%u, mian_thread_id:%lu\n", getpid(), main_thread_id); ret = pthread_create(thread_id, NULL, function1, NULL); assert(ret == 0); ret = pthread_create(thread_id + 1, NULL, function2, NULL); assert(ret == 0); ret = pthread_join(thread_id[0], NULL); assert(ret == 0); ret = pthread_join(thread_id[1], NULL); assert(ret == 0); core = 2 % cpu_nums; CPU_ZERO(&cpuset); CPU_SET(core, &cpuset); ret = pthread_setaffinity_np(main_thread_id, sizeof(cpu_set_t), &cpuset); assert(ret == 0); /* Check the actual affinity mask assigned to the thread */ ret = pthread_getaffinity_np(main_thread_id, sizeof(cpu_set_t), &cpuset); assert(ret == 0); printf("mian_thread_id:%lu set the cpu:", main_thread_id); for (j = 0; j < CPU_SETSIZE; j++) if (CPU_ISSET(j, &cpuset)) printf(" CPU %d \n\n", j); printf ("the main function pthread id is %lu, bind core %d result: %f\n", main_thread_id, core, waste_time (5000)); return 0; }
gcc 编译:
$ gcc thread_affi.c -lpthread -lm
执行程序时可以通过top命令,然后按‘1’,查看各个cpu的使用情况.