天天看點

c++ 線程綁定到cpu指定核心

将線程綁定到cpu指定核心可以避免線程函數在多個核心上執行,進而減少線程間通信的開銷,也友善檢視負載,便于比較不同線程之間負載是否均衡。

cpu的聲明(變量類型)cpu_set_t

綁定程序主要是通過三個函數,這三個函數都是線上程函數裡面調用的

CPU_ZERO(&cpu_size_t)  cpu初始化,将這個cpu置為空

CPU_SET(int,cpu_size_t&)  int是cpu核的編号,這是一個設定具體哪個核的過程。專業名詞叫親和力,線程綁定核都是通過親和力來完成的

sched_setaffinity(int,sizeof(cpu_set_t),&cpu_set_t)将線程與cpu核綁定,具體綁定哪個核通過上一步的CPU_SET已經确定int為0時表示此線程函數

#include <stdlib.h>
#include <stdio.h>
// #include <sys/types.h>
// #include <sys/sysinfo.h>
#include <unistd.h>

#define __USE_GUN
// #include <sched.h>
// #include <ctype.h>
#include <string.h>
#include <pthread.h>
#define THREAD_MAX_NUM 100// 1個cpu内最多程序數
int num=0; //cpu中核數

void* threadFun(void* arg)// arg傳遞線程标号,自己定義
{
    //sleep(2);
    cpu_set_t mask;// cpu核的集合
    cpu_set_t get;// 擷取在集合中的cpu
    int* a=(int*)arg;
    printf("this is: %d\n",*a);// 列印這是第幾個線程
    CPU_ZERO(&mask);// 将集合置為空集
    CPU_SET(*a,&mask);// 設定親和力值

    if(sched_setaffinity(0,sizeof(cpu_set_t),&mask)==-1)// 設定線程cpu親和力
    {
        printf("warning: could not set CPU affinity, continuing...\n");
    }
    while(1)
    {
        CPU_ZERO(&get);
        if(sched_getaffinity(0,sizeof(get),&get)==-1)// 擷取線程cpu親和力
        {
            printf("warning: could not get thread affinity, continuing...\n");
        }
        for(int i=0;i<num;++i)
        {
            if(CPU_ISSET(i,&get))// 判斷線程與哪個cpu有親和力
            {
                //printf("this thread %d is running processor: %d\n",i,i);
                int a=1000000*1000000;
            }
        }
    }
    return NULL;
}

int main(void)
{
    num=sysconf(_SC_NPROCESSORS_CONF);// 擷取核數
    pthread_t thread[THREAD_MAX_NUM];
    printf("system has %i processor(s).\n",num);
    int tid[THREAD_MAX_NUM];
    for(int i=0;i<10;++i)
    {
        if(i%2==0)
        {
            tid[i]=i;// 每個線程必須有個tid[i]
            pthread_create(&thread[i],NULL,threadFun,(void*)&tid[i]);
        }
        //sleep(2);
    }
    for(int i=0;i<num;++i)
    {
        pthread_join(thread[i],NULL);
    }
    return 0;
}      

注意線程庫的選擇,用c++自帶的線程庫<thread>是不可以的,這個庫裡的線程無法綁定到cpu核,必須使用<pthread.h>

num=sysconf(_SC_NPROCESSORS_CONF);是擷取該計算機的cpu有多少核,在頭檔案<unistd.h>中定義

<pthread.h>中包含了<sched.h>是以不需要重複引用

CPU_SET這些函數都是通過宏來實作的,通過操作cpu_set_t的補碼,我沒有去仔細研究,

該程式的意思是0~9取偶數作為cpu核的id,将線程函數綁定在偶數核上

在CMakeLists.txt檔案中要加上set(CMAKE_CXX_FLAGS "${CAMKE_CXX_FLAGS} -std=c++11 -pthread")

結果如下

c++ 線程綁定到cpu指定核心

 通過top檢視詳細資訊

c++ 線程綁定到cpu指定核心

 接着按1檢視cpu核詳情

c++ 線程綁定到cpu指定核心

 cpu 0,2,4,6,8上運作線程,其他核沒有