cpu绑定和cpu亲和性

来源:互联网 发布:淘宝靠谱iphone 编辑:程序博客网 时间:2024/06/06 21:04

将进程/线程与cpu绑定,最直观的好处就是提高了cpu cache的命中率,从而减少内存访问损耗,提高程序的速度。我觉得在NUMA架构下,这个操作对系统运行速度的提升有较大的意义,而在SMP架构下,这个提升可能就比较小。这主要是因为两者对于cache、总线这些资源的分配使用方式不同造成的,NUMA每个cpu有自己的一套资源体系, SMP中每个核心还是需要共享这些资源的,从这个角度来看,NUMA使用cpu绑定时,每个核心可以更专注地处理一件事情,资源体系被充分使用,减少了同步的损耗。SMP由于一部分资源的共享,在进行了绑定操作后,受到的影响还是很大的。

通过linux提供的几个api, 可以轻松地完成这个优化:

#define _GNU_SOURCE             #include <sched.h>int sched_setaffinity(pid_t pid, size_t cpusetsize,cpu_set_t *mask);    //设定pid 绑定的cpu, int sched_getaffinity(pid_t pid, size_t cpusetsize,cpu_set_t *mask);    //查看pid 绑定的cpu。

cpu_set_t  //是一个掩码数组,一共有1024位,每一位都可以对应一个cpu核心//以下宏,都是对这个掩码进行操作的。如果需要,一个进程是可以绑定多个cpu的。void CPU_ZERO(cpu_set_t *set);void CPU_SET(int cpu, cpu_set_t *set);void CPU_CLR(int cpu, cpu_set_t *set);int CPU_ISSET(int cpu, cpu_set_t *set); 

下面是一个实例。

/* * @FileName: simple_affinity.c * @Author: wzj * @Brief:  * 1. cpu affinity.  case * 2.在子线程中,会继承绑定的cpu..., 不过在子线程中,可以重新分配。 *   * @History:  *  *  *  * @Date: 2012年04月21日星期六12:56:14 *  */ #include <stdlib.h>#include <stdio.h>#include <unistd.h>#define __USE_GNU//启用CPU_ZERO等相关的宏//#define _GNU_SOURCE#include <sched.h>#include <pthread.h>            //这个东西原来放在__USE_GNU宏之前,结果被编译器报错说CPU_ZERO未定义void* new_test_thread(void* arg){cpu_set_t mask;int i = 0;int num = sysconf(_SC_NPROCESSORS_CONF);    //获取当前的cpu总数pthread_detach(pthread_self());CPU_ZERO(&mask);CPU_SET(1, &mask);      //绑定cpu 1if(sched_setaffinity(0, sizeof(mask), &mask) == -1)      //0 代表对当前线程/进程进行设置。{printf("set affinity failed..");}while(1){CPU_ZERO(&mask);if(sched_getaffinity(0, sizeof(mask), &mask) == -1){printf("get failed..\n");}for(i = 0; i < num; i++){if(CPU_ISSET(i, &mask))printf("new thread %d run on processor %d\n", getpid(), i);}while(1);sleep (1);}}      //while(1);      //如果觉得不明显,改成这个,

void* child_test_thread(void* arg){cpu_set_t mask;int i = 0;int num = sysconf(_SC_NPROCESSORS_CONF);pthread_detach(pthread_self());while(1){CPU_ZERO(&mask);if(sched_getaffinity(0, sizeof(mask), &mask) == -1){printf("get failed..\n");}for(i = 0; i < num; i++){if(CPU_ISSET(i, &mask))printf("child thread %d run on processor %d\n", getpid(), i);}sleep (1);}}intmain(int argc, char* argv[]){int num = sysconf(_SC_NPROCESSORS_CONF);int created_thread = 0;int myid;int i;int j = 0;pthread_t ptid = 0;cpu_set_t mask;cpu_set_t get;if(argc != 2){printf("usage: ./cpu num\n");return -1;}myid = atoi(argv[1]);printf("system has %i processor(s).\n", num);CPU_ZERO(&mask);CPU_SET(myid, &mask);if(sched_setaffinity(0, sizeof(mask), &mask) == -1){printf("warning: set CPU affinity failed...");}int ret = pthread_create(&ptid, NULL, new_test_thread, NULL);if(ret){return -1;}ret = pthread_create(&ptid, NULL, child_test_thread, NULL);if(ret){return -1;}while(1){CPU_ZERO(&get);if(sched_getaffinity(0, sizeof(get), &get) == -1){printf("can't get cpu affinity...");}for(i = 0; i < num; i++){if(CPU_ISSET(i, &get)){printf("this process %d is runing on procesor:%d\n", getpid(), i);}}sleep(1);}//while(1); //使用这个更明显return 0;}

编译:

gcc -o cpu simple_affinity.c -lpthread

执行./cpu [cpu num / masks] ,使用top观察cpu使用状况。 使用./cpu 0 时,可以发现,两颗核心使用率都比较高, 使用./cpu 1时,可以发现,1核的压力比较重。


当然还可以对线程进行cpu绑定。

#define _GNU_SOURCE#include <pthread.h> int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize,                          const cpu_set_t *cpuset);int pthread_getaffinity_np(pthread_t thread, size_t cpusetsize,                          cpu_set_t *cpuset);


这个介绍了使用的时机,比较经典:http://www.ibm.com/developerworks/cn/linux/l-affinity.html



原创粉丝点击