Linux中线程与CPU核的绑定

 

最近在对项目进行性能优化,由于在多核平台上,所以了解了些进程、线程绑定cpu核的问题,在这里将所学记录一下。
    不管是线程还是进程,都是通过设置亲和性(affinity)来达到目的。对于进程的情况,一般是使用sched_setaffinity这个函数来实现,网上讲的也比较多,这里主要讲一下线程的情况。
    与进程的情况相似,线程亲和性的设置和获取主要通过下面两个函数来实现:
int pthread_setaffinity_np(pthread_tthread, size_tcpusetsize,
const cpu_set_t *cpuset);
int pthread_getaffinity_np(pthread_t thread, size_tcpusetsize, 
cpu_set_t *cpuset);
    从函数名以及参数名都很明了,唯一需要点解释下的可能就是cpu_set_t这个结构体了。这个结构体的理解类似于select中的fd_set,可以理解为cpu集,也是通过约定好的宏来进行清除、设置以及判断:
//初始化,设为空
      void CPU_ZERO (cpu_set_t *set); 
      //将某个cpu加入cpu集中 
       void CPU_SET (int cpu, cpu_set_t *set); 
       //将某个cpu从cpu集中移出 
       void CPU_CLR (int cpu, cpu_set_t *set); 
       //判断某个cpu是否已在cpu集中设置了 
       int CPU_ISSET (int cpu, const cpu_set_t *set); 
       cpu集可以认为是一个掩码,每个设置的位都对应一个可以合法调度的 cpu,而未设置的位对应一个不可调度的 CPU。换而言之,线程都被绑定了,只能在那些对应位被设置了的处理器上运行。通常,掩码中的所有位都被置位了,也就是可以在所有的cpu中调度。       
      以下为测试代码:

点击(此处)折叠或打开

  1. #define _GNU_SOURCE
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <unistd.h>
  6. #include <pthread.h>
  7. #include <sched.h>

  8. void *myfun(void*arg)
  9. {
  10.     cpu_set_t mask;
  11.     cpu_set_t get;
  12.     char buf[256];
  13.     int i;
  14.     int j;
  15.     int num= sysconf(_SC_NPROCESSORS_CONF);
  16.     printf("system has %d processor(s)\n", num);

  17.     for(i= 0; i< num; i++){
  18.         CPU_ZERO(&mask);
  19.         CPU_SET(i,&mask);
  20.         if(pthread_setaffinity_np(pthread_self(), sizeof(mask),&mask)< 0){
  21.             fprintf(stderr,"set thread affinity failed\n");
  22.         }
  23.         CPU_ZERO(&get);
  24.         if(pthread_getaffinity_np(pthread_self(), sizeof(get),&get)< 0){
  25.             fprintf(stderr,"get thread affinity failed\n");
  26.         }
  27.         for(j= 0; j< num; j++){
  28.             if(CPU_ISSET(j,&get)){
  29.                 printf("thread %d is running in processor %d\n",(int)pthread_self(), j);
  30.             }
  31.         }
  32.         j = 0;
  33.         while(j++< 100000000){
  34.             memset(buf, 0, sizeof(buf));
  35.         }
  36.     }
  37.     pthread_exit(NULL);
  38. }

  39. int main(int argc, char*argv[])
  40. {
  41.     pthread_t tid;
  42.     if(pthread_create(&tid,NULL,(void*)myfun,NULL)!= 0){
  43.         fprintf(stderr,"thread create failed\n");
  44.         return -1;
  45.     }
  46.     pthread_join(tid,NULL);
  47.     return 0;
  48. }
       这段代码将使myfun线程在所有cpu中依次执行一段时间,在我的四核cpu上,执行结果为  :
       system has 4 processor(s)        
       thread 1095604544 is running in processor 0        
       thread 1095604544 is running in processor 1        
       thread 1095604544 is running in processor 2        
       thread 1095604544 is running in processor 3 
       在一些嵌入式设备中,运行的进程线程比较单一,如果指定进程线程运行于特定的cpu核,减少进程、线程的核间切换,有可能可以获得更高的性能。
 
二 windows
通过调用SetThreadAffinityMask,就能为各个线程设置亲缘性屏蔽:
DWORD_PTR SetThreadAffinityMask(HANDLE hThread,
   DWORD_PTR dwThreadAffinityMask);
该函数中的h T h r e a d参数用于指明要限制哪个线程, dwThreadAffinityMask用于指明该线程能够在哪个CPU上运行。dwThreadAffinityMask必须是进程的亲缘性屏蔽的相应子集。返回值是线程的前一个亲缘性屏蔽。因此,若要将3个线程限制到CPU1、2和3上去运行,可以这样操作:
//Thread 0 can only run on CPU 0.
SetThreadAffinityMask(hThread0, 0x00000001);

//Threads 1, 2, 3 run on CPUs 1, 2, 3.
SetThreadAffinityMask(hThread1, 0x0000000E);
SetThreadAffinityMask(hThread2, 0x0000000E);
SetThreadAffinityMask(hThread3, 0x0000000E);

 

三 linux

 cpu_set_t mask;

        cpu_set_t get;

        int i;

  

        int num = sysconf(_SC_NPROCESSORS_CONF);

        printf("system has %d processor(s)\n", num);

        CPU_ZERO(&mask);

        CPU_SET(1, &mask);           //指定运行在哪个CPU上。我们linux机器(Linux version 2.6.32-5-amd64 (Debian 2.6.32-35))4CPU,其编号为0-3

        pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask);

        for (i = 0;; i++) {  //此循环导致CPU占用率为100%

            if (!(i%10000))

            {  

                std::vector<int> myvector;

                for (int i = 0; i < 1000;i++)

                {

                    myvector.push_back(i);

                }

            }

        }

 


Logo

更多推荐