CPU绑定和CPU亲和性

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

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

#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); 


 
 

下面是一个实例。

[cpp]  view plain copy
  1. /* 
  2.  * @FileName: simple_affinity.c 
  3.  * @Author: wzj 
  4.  * @Brief:  
  5.  * 1. cpu affinity.  case 
  6.  * 2.在子线程中,会继承绑定的cpu..., 不过在子线程中,可以重新分配。 
  7.  *   
  8.  * @History:  
  9.  *  
  10.  *  
  11.  *  
  12.  * @Date: 2012年04月21日星期六12:56:14 
  13.  *  
  14.  */   
  15.   
  16. #include <stdlib.h>  
  17. #include <stdio.h>  
  18. #include <unistd.h>  
  19.   
  20. #define __USE_GNU       //启用CPU_ZERO等相关的宏  
  21. //#define _GNU_SOURCE  
  22. #include <sched.h>  
  23. #include <pthread.h>            //这个东西原来放在__USE_GNU宏之前,结果被编译器报错说CPU_ZERO未定义  
  24.   
  25. void* new_test_thread(void* arg)  
  26. {  
  27.     cpu_set_t mask;  
  28.     int i = 0;  
  29.     int num = sysconf(_SC_NPROCESSORS_CONF);    //获取当前的cpu总数  
  30.     pthread_detach(pthread_self());  
  31.       
  32.     CPU_ZERO(&mask);      
  33.     CPU_SET(1, &mask);      //绑定cpu 1  
  34.     if(sched_setaffinity(0, sizeof(mask), &mask) == -1)      //0 代表对当前线程/进程进行设置。  
  35.     {  
  36.         printf("set affinity failed..");  
  37.     }  
  38.     while(1)  
  39.     {  
  40.         CPU_ZERO(&mask);  
  41.         if(sched_getaffinity(0, sizeof(mask), &mask) == -1)   
  42.         {  
  43.             printf("get failed..\n");  
  44.         }  
  45.   
  46.         for(i = 0; i < num; i++)  
  47.         {  
  48.             if(CPU_ISSET(i, &mask))  
  49.             printf("new thread %d run on processor %d\n", getpid(), i);  
  50.         }  
  51.         while(1);  
  52.         sleep (1);  
  53.     }  
  54. }      //while(1);      //如果觉得不明显,改成这个,  

[cpp]  view plain copy
  1. void* child_test_thread(void* arg)  
  2. {  
  3.     cpu_set_t mask;  
  4.     int i = 0;  
  5.     int num = sysconf(_SC_NPROCESSORS_CONF);  
  6.     pthread_detach(pthread_self());  
  7.       
  8.     while(1)  
  9.     {  
  10.         CPU_ZERO(&mask);  
  11.         if(sched_getaffinity(0, sizeof(mask), &mask) == -1)   
  12.         {  
  13.             printf("get failed..\n");  
  14.         }  
  15.   
  16.         for(i = 0; i < num; i++)  
  17.         {  
  18.             if(CPU_ISSET(i, &mask))  
  19.             printf("child thread %d run on processor %d\n", getpid(), i);  
  20.         }  
  21.         sleep (1);  
  22.     }  
  23.   
  24. }  
  25.   
  26. int  
  27. main(int argc, char* argv[])  
  28. {  
  29.     int num = sysconf(_SC_NPROCESSORS_CONF);  
  30.     int created_thread = 0;  
  31.     int myid;  
  32.     int i;  
  33.     int j = 0;  
  34.     pthread_t ptid = 0;  
  35.   
  36.     cpu_set_t mask;  
  37.     cpu_set_t get;  
  38.   
  39.     if(argc != 2)  
  40.     {  
  41.         printf("usage: ./cpu num\n");  
  42.         return -1;  
  43.     }  
  44.     myid = atoi(argv[1]);  
  45.     printf("system has %i processor(s).\n", num);  
  46.   
  47.     CPU_ZERO(&mask);  
  48.     CPU_SET(myid, &mask);  
  49.     if(sched_setaffinity(0, sizeof(mask), &mask) == -1)  
  50.     {  
  51.         printf("warning: set CPU affinity failed...");  
  52.     }  
  53.   
  54.     int ret = pthread_create(&ptid, NULL, new_test_thread, NULL);  
  55.     if(ret)  
  56.     {  
  57.         return -1;  
  58.     }  
  59.     ret = pthread_create(&ptid, NULL, child_test_thread, NULL);  
  60.     if(ret)  
  61.     {  
  62.         return -1;  
  63.     }  
  64.   
  65.   
  66.     while(1)  
  67.     {  
  68.         CPU_ZERO(&get);  
  69.         if(sched_getaffinity(0, sizeof(get), &get) == -1)  
  70.         {  
  71.             printf("can't get cpu affinity...");  
  72.         }  
  73.   
  74.         for(i = 0; i < num; i++)  
  75.         {  
  76.             if(CPU_ISSET(i, &get))  
  77.             {  
  78.                 printf("this process %d is runing on procesor:%d\n", getpid(), i);  
  79.             }  
  80.         }  
  81.           
  82.         sleep(1);  
  83.     }  
  84.     //while(1); //使用这个更明显  
  85.     return 0;  
  86. }  

编译:

[cpp]  view plain copy
  1. gcc -o cpu simple_affinity.c -lpthread  

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


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

[cpp]  view plain copy
  1. #define _GNU_SOURCE  
  2. #include <pthread.h>  
  3.    
  4. int pthread_setaffinity_np(pthread_t threadsize_t cpusetsize,  
  5.                           const cpu_set_t *cpuset);  
  6. int pthread_getaffinity_np(pthread_t threadsize_t cpusetsize,  
  7.                           cpu_set_t *cpuset);  


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


转自:http://blog.csdn.net/joker0910/article/details/7484371
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值