0


linux C++实现线程绑定CPU

前言

嵌入式里面我们会使用到多核的cpu,随着产品芯片性能提升,我们也会有很多功能,以及很多进程产生运行,这个时候我们在任务调度调优的时候,把一些进程绑定到固定cpu运行,下面就来分享一下cpu绑定运行的过程:
首先运行的环境需要多核,大家可以按照下面命令进行查询对应设备的cpu数量
使用cat /proc/cpuinfo查看cpu信息,如下两个信息:
processor,指明第几个cpu处理器
cpu cores,指明每个处理器的核心数
请添加图片描述

基本概念

cpu亲和性(affinity)

CPU的亲和性, 就是进程要在指定的 CPU 上尽量长时间地运行而不被迁移到其他处理器,也称为CPU关联性;再简单的点的描述就将指定的进程或线程绑定到相应的cpu上;在多核运行的机器上,每个CPU本身自己会有缓存,缓存着进程使用的信息,而进程可能会被OS调度到其他CPU上,如此,CPU cache命中率就低了,当绑定CPU后,程序就会一直在指定的cpu跑,不会由操作系统调度到其他CPU上,性能有一定的提高。
软亲和性(affinity)
就是进程要在指定的 CPU 上尽量长时间地运行而不被迁移到其他处理器,Linux 内核进程调度器天生就具有被称为 软 CPU 亲和性(affinity) 的特性,这意味着进程通常不会在处理器之间频繁迁移。这种状态正是我们希望的,因为进程迁移的频率小就意味着产生的负载小。
硬亲和性(affinity)
简单来说就是利用linux内核提供给用户的API,强行将进程或者线程绑定到某一个指定的cpu核运行。

代码绑定实现

上面我们使用cat /proc/cpuinfo命令查询了自己设备的CPU,以我为例,我的电脑从0~7一共有8核。
下面是代码的demo:

#include<stdio.h>#include<unistd.h>#include<thread>voidthread_func1(){
        cpu_set_t mask;CPU_ZERO(&mask);CPU_SET(1,&mask);//指定该线程使用的CPUif(pthread_setaffinity_np(pthread_self(),sizeof(mask),&mask)<0){perror("pthread_setaffinity_np");}int count =0;while(1){
                count ++;sleep(1);printf("fun 1 cnt :%d \n",count);for(int i =0; i <8; i++){if(CPU_ISSET(i,&mask))//查看cpu i 是否在get 集合当中{printf("1 this process %d of running processor: %d\n",getpid(), i);}}}}voidthread_func2(){int count =0;
        cpu_set_t mask;CPU_ZERO(&mask);CPU_SET(5,&mask);if(pthread_setaffinity_np(pthread_self(),sizeof(mask),&mask)<0){perror("pthread_setaffinity_np");}while(1){usleep(1000*1000);
                count ++;printf("fun 2 cnt :%d \n",count);for(int i =0; i <8; i++){if(CPU_ISSET(i,&mask))//查看cpu i 是否在get 集合当中{printf("2 this process %d of running processor: %d\n",getpid(), i);}}}}intmain(int argc,char*argv[]){int cpus =0;

        cpus =sysconf(_SC_NPROCESSORS_CONF);printf("cpus: %d\n", cpus);//查看cpu的个数;

    cpu_set_t mask;CPU_ZERO(&mask);CPU_SET(7,&mask);if(sched_setaffinity(0,sizeof(mask),&mask)<0){perror("sched_setaffinity");}

    std::thread t1(thread_func1);
    std::thread t2(thread_func2);usleep(1000);/* 让当前的设置有足够时间生效*/while(1){/*查看运行在当前进程的cpu*/sleep(1);/* 让当前的设置有足够时间生效*/printf("fun main \n");for(int i =0; i < cpus; i++){if(CPU_ISSET(i,&mask))//查看cpu i 是否在get 集合当中{printf("3 this process %d of running processor: %d\n",getpid(), i);}}}
    t1.join();
    t2.join();}

上面一共运行了三个线程,一个是main 主线程,还有两个是自己定义的thread。
最重要的设置代码就是下面所示:设置cpu 亲和

cpu_set_t mask;CPU_ZERO(&mask);/* 初始化set集,将set置为空*/CPU_SET(5,&mask);/* 将对应的cpu序号加入到集合*/if(pthread_setaffinity_np(pthread_self(),sizeof(mask),&mask)<0)/*设置cpu 亲和性(affinity)*/{perror("pthread_setaffinity_np");}

执行代码
请添加图片描述

代码绑定查看

使用ps -ef | grep a.out 命令查看对应的PID
请添加图片描述使用 top命令查看对应pid的线程详细信息 top -p 14617请添加图片描述在进入top命令后,继续输入 f
请添加图片描述使用上下 移动高亮到p
请添加图片描述空格 选中
再按q 退出显示
输入大写H
就可以看到对应线程数据了请添加图片描述

注意事项

虽然绑核技术可以提高程序性能,但也需要注意以下几点:

  1. 不要过度绑定:过度绑定可能会出现线程之间的竞争和CPU利用率低下的情况。
  2. 绑定前需要评估:在进行核心绑定之前,需要对程序进行评估,以确定性能瓶颈位置和绑定的核心数。
  3. 不要跨核心访问内存:如果一个进程已经绑定到一个核心上,那么该进程所使用的内存也只应该在该核心专用的内存上进行操作。如果在不同核心之间频繁地进行内存操作,则会影响程序的性能。

引用https://blog.csdn.net/lyn631579741/article/details/123337907

标签: linux c++ java

本文转载自: https://blog.csdn.net/lzy6041/article/details/134262271
版权归原作者 什么都会一点儿的自动驾驶工程狮 所有, 如有侵权,请联系我们删除。

“linux C++实现线程绑定CPU”的评论:

还没有评论