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的补码,我没有去仔细研究,参考这个:https://blog.csdn.net/STN_LCD/article/details/78134574
该程序的意思是0~9取偶数作为cpu核的id,将线程函数绑定在偶数核上
在CMakeLists.txt文件中要加上set(CMAKE_CXX_FLAGS "${CAMKE_CXX_FLAGS} -std=c++11 -pthread")
结果如下

 

 通过top查看详细信息

 

 接着按1查看cpu核详情

 

 cpu 0,2,4,6,8上运行线程,其他核没有

  

 
posted @ 2022-02-21 16:47  Wangtn  阅读(6224)  评论(0编辑  收藏  举报