• cpu绑定和cpu亲和性


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

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

    [cpp] view plaincopy
     
    1. #define _GNU_SOURCE               
    2. #include <sched.h>  
    3.   
    4. int sched_setaffinity(pid_t pid, size_t cpusetsize,cpu_set_t *mask);    //设定pid 绑定的cpu,   
    5. int sched_getaffinity(pid_t pid, size_t cpusetsize,cpu_set_t *mask);    //查看pid 绑定的cpu。  
    
    
    [cpp] view plaincopy
     
    1. cpu_set_t  //是一个掩码数组,一共有1024位,每一位都可以对应一个cpu核心  
    2. //以下宏,都是对这个掩码进行操作的。如果需要,一个进程是可以绑定多个cpu的。  
    3. void CPU_ZERO(cpu_set_t *set);  
    4. void CPU_SET(int cpu, cpu_set_t *set);  
    5. void CPU_CLR(int cpu, cpu_set_t *set);  
    6. int CPU_ISSET(int cpu, cpu_set_t *set);  
    7.    

    下面是一个实例。

    [cpp] view plaincopy
     
    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.. ");  
    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 ", getpid(), i);  
    50.         }  
    51.         while(1);  
    52.         sleep (1);  
    53.     }  
    54. }      //while(1);      //如果觉得不明显,改成这个,  
    [cpp] view plaincopy
     
    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.. ");  
    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 ", 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 ");  
    42.         return -1;  
    43.     }  
    44.     myid = atoi(argv[1]);  
    45.     printf("system has %i processor(s). ", 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 ", getpid(), i);  
    79.             }  
    80.         }  
    81.           
    82.         sleep(1);  
    83.     }  
    84.     //while(1); //使用这个更明显  
    85.     return 0;  
    86. }  

    编译:

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


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

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

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



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

  • 相关阅读:
    count-and-say
    jump-game
    trapping-rain-water
    Java QueueDemo
    Java StackDemo
    swap-nodes-in-pairs
    php多维数组变成一维数组
    php获取客户端IP地址
    php根据随机数生成6位密钥
    Laravel ,YII,thinkphp 框架的区别
  • 原文地址:https://www.cnblogs.com/banwhui/p/4977338.html
Copyright © 2020-2023  润新知