Linux编程之《进程/线程绑定CPU》

Intro
-----

通常我们在编写服务器代码时,可以通过将当前进程绑定到固定的CPU核心或者线程绑定到固定的CPU核心来提高系统调度程序的效率来提高程序执行的效率,下面将完整代码贴上。
```
/************************************************
* 该例程讲解了进程、线程绑定到固定的cpu核心上运行
* 来提高程序运行效率
************************************************/
#include <unistd.h>
#ifndef __USE_GNU
#define __USE_GNU // 为了使用SET_SET()等宏定义,但unistd.h里面好像已经定义了
#endif
#include <sched.h>
#include <pthread.h>
#include <stdio.h>
#include <vector>

unsigned int systemCPUNum()
{
// _SC_NPROCESSORS_CONF的值为CPU个数,基于0开始编号
return sysconf(_SC_NPROCESSORS_CONF);
}

bool currentProcessAffinity(std::vector<unsigned int>& runningCPUVector)
{
cpu_set_t cpuSet;

// 清空一个CPU集合
CPU_ZERO(&cpuSet);

// 得到指定进程ID绑定到哪个CPU
int ret = sched_getaffinity(0, // 0代表当前进程
sizeof(cpuSet),
&cpuSet);
if (ret < 0)
{
return false;
}

unsigned int cpuNum = systemCPUNum();
runningCPUVector.clear();
for (unsigned int i = 0; i < cpuNum; ++i)
{
// 检查一个CPU号是否在一个集合中
if (CPU_ISSET(i, &cpuSet))
{
runningCPUVector.push_back(i);
}
}

return true;
}

bool setCurrentProcessAffinity(const std::vector<unsigned int>& needBindCPUVector)
{
cpu_set_t cpuSet;

// 清空一个CPU集合
CPU_ZERO(&cpuSet);

for (auto& iter : needBindCPUVector)
{
CPU_SET(iter, &cpuSet);
}

// 将指定进程ID绑定到CPU
int ret = sched_setaffinity(0, // 0代表当前进程
sizeof(cpuSet),
&cpuSet);
if (ret < 0)
{
return false;
}

return true;
}

bool currentThreadAffinity(std::vector<unsigned int>& runningCPUVector)
{
cpu_set_t cpuSet;

// 清空一个CPU集合
CPU_ZERO(&cpuSet);

// 得到指定线程ID绑定到哪个CPU
int ret = pthread_getaffinity_np(pthread_self(),
sizeof(cpuSet),
&cpuSet);
if (ret < 0)
{
return false;
}

unsigned int cpuNum = systemCPUNum();
runningCPUVector.clear();
for (unsigned int i = 0; i < cpuNum; ++i)
{
// 检查一个CPU号是否在一个集合中
if (CPU_ISSET(i, &cpuSet))
{
runningCPUVector.push_back(i);
}
}

return true;
}

bool setCurrentThreadAffinity(const std::vector<unsigned int>& needBindCPUVector)
{
cpu_set_t cpuSet;

// 清空一个CPU集合
CPU_ZERO(&cpuSet);

for (auto& iter : needBindCPUVector)
{
CPU_SET(iter, &cpuSet);
}

// 将指定线程ID绑定到CPU
int ret = pthread_setaffinity_np(pthread_self(),
sizeof(cpuSet),
&cpuSet);
if (ret < 0)
{
return false;
}

return true;
}

int main()
{
printf("*****Process bind CPU sample*****\n");
unsigned int cpuNum = systemCPUNum();
printf("Current system has %u CPU(s)\n", cpuNum);

std::vector<unsigned int> runningCPUVector;
if (!currentProcessAffinity(runningCPUVector))
{
printf("Get current process was bound witch CPU failed\n");
return 1;
}

for (auto& iter : runningCPUVector)
{
printf("Current process is running at %u CPU\n", iter);
}

std::vector<unsigned int> needBindCPUVector {0, 2};
if (!setCurrentProcessAffinity(needBindCPUVector))
{
printf("Current process bind CPU failed\n");
return 1;
}

printf("Current process bind CPU success\n");

runningCPUVector.clear();
if (!currentProcessAffinity(runningCPUVector))
{
printf("Get current process was bound witch CPU failed\n");
return 1;
}

for (auto& iter : runningCPUVector)
{
printf("Current process is running at %u CPU\n", iter);
}

printf("\n*****Thread bind CPU sample*****\n");
runningCPUVector.clear();
if (!currentThreadAffinity(runningCPUVector))
{
printf("Get current thread was bound witch CPU failed\n");
return 1;
}

for (auto& iter : runningCPUVector)
{
printf("Thread %lu is running at %u CPU\n", pthread_self(), iter);
}

needBindCPUVector.clear();
needBindCPUVector.push_back(1);
if (!setCurrentThreadAffinity(needBindCPUVector))
{
printf("Current thread bind CPU failed\n");
return 1;
}

printf("Thread %lu bind CPU success\n", pthread_self());

runningCPUVector.clear();
if (!currentThreadAffinity(runningCPUVector))
{
printf("Get current thread was bound witch CPU failed\n");
return 1;
}

for (auto& iter : runningCPUVector)
{
printf("Thread %lu is running at %u CPU\n", pthread_self(), iter);
}

return 0;
}
```

程序执行的输出结果:
```
*****Process bind CPU sample*****
Current system has 4 CPU(s)
Current process is running at 0 CPU
Current process is running at 1 CPU
Current process is running at 2 CPU
Current process is running at 3 CPU
Current process bind CPU success
Current process is running at 0 CPU
Current process is running at 2 CPU

*****Thread bind CPU sample*****
Thread 139871129114432 is running at 0 CPU
Thread 139871129114432 is running at 2 CPU
Thread 139871129114432 bind CPU success
Thread 139871129114432 is running at 1 CPU
```

该例子的github地址:https://github.com/chxuan/samples/blob/master/BindCPU/BindCPU.cpp

时间: 2024-10-26 02:00:09

Linux编程之《进程/线程绑定CPU》的相关文章

linux下将不同线程绑定到不同core和cpu上——pthread_setaffinity_np

=============================================================== linux下的单进程多线程的程序,要实现每个线程平均分配到多核cpu,主要有2个方法 1:利用linux系统自己的线程切换机制,linux有一个服务叫做irqbalance,这个服务是linux系统自带的,默认会启动,这个服务的作用就是把多线程平均分配到CPU的每个核上面,只要这个服务不停止,多线程分配就可以自己实现.但是要注意,如果线程函数内部的有某个循环,且该循环内

linux系统知识 - 进程&amp;线程

作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 参考链接 http://www.cnblogs.com/vamei/archive/2012/09/20/2694466.html http://www.cnblogs.com/vamei/archive/2012/10/09/2715393.html 背景知识 指令:计算机能做的事情其实非常简单,比如计算两个数之和.寻找到内存中的某个地址.这些最基础的计算机动作称为指令. 程序

【Linux编程】进程标识符与fork函数

ID为0的进程一般是调度进程.常被称为交换进程(swapper),是内核中的系统进程. ID为1的进程叫做init进程,是一个普通用户进程,不属于内核,由内核调用. 一个现有进程能够调用fork函数创建一个新进程(子进程).fork函数被调用一次.返回两次. 子进程返回值为0.父进程返回值为子进程的进程ID. 当fork出一个子进程后,子进程便拥有独立的数据段.堆.栈的副本,但父.子进程共享正文段(关于程序分布见文章"C程序的存储空间布局").但如今非常多实现并不全然复制数据段.堆.栈

为线程绑定CPU

// learn gcc atomic variable #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #include <sys/syscall.h> #include <linux/unistd.h> #include <errno.h> #include <s

Windows10 临时将线程绑定至指定CPU的方法

本文首发:https://www.somata.work/2019/WindowsThreadBind.html 将线程绑定至指定CPU,这个应该时很多管理员需要了解认知的操作了吧,这样可以在一定程度上加快那么一丢丢程序运行速度,同时最重要的就是可以通过限制程序的运行CPU范围来保证至少有1颗CPU不会满状态运行,不至于卡到宕机,从而不影响后期维护. 那么这里将会介绍如何在Windows中临时设置绑定CPU的方法,下面来看操作即可 通过任务管理器绑定CPU 首先右键 Windows 菜单,选择任

linux之C编程学习——进程,进程,进程!

linux支持多个进程同时进行,也就是我们常说的现代操作系统中的多道程序设计,所谓同时是linux系统调度各个进程分别占用cpu的时间.由于每个时间片的时间很小和宏观时间相比,给人的感觉是多个进程在运行.为了提高程序的运行效率,程序往往分成多个部分组成,这也就是说的并发程序设计.并发程序中各进程是相互独立的,在必要的时候会通过相应的机制进行通信.若进程间要共享资源,为了避免出现冲突,常通过相应通信机制使它们轮流使用共享资源.在进程进行通信时,会出现一个进程等另一个进程完,才能继续运行的情况,这也

多线程程序 怎样查看每个线程的cpu占用

可以用下面的命令将 cpu 占用率高的线程找出来: ps H -eo user,pid,ppid,tid,time,%cpu,cmd --sort=%cpu 这个命令首先指定参数'H',显示线程相关的信息,格式输出中包含:user,pid,ppid,tid,time,%cpu,cmd,然后再用%cpu字段进行排序.这样就可以找到占用处理器的线程了. 直接使用 ps Hh -eo pid,tid,pcpu | sort -nk3 |tail 获取对于的进程号和线程号,然后跳转到3.查看哪个进程线程

NGINX源码剖析 之 CPU绑定(CPU亲和性)

作者:邹祁峰 邮箱:[email protected] 博客:http://blog.csdn.net/qifengzou 日期:2014.06.12 18:44 转载请注明来自"祁峰"的CSDN博客 1 引言   非统一内存访问(NUMA)是一种用于多处理器的电脑记忆体设计,内存访问时间取决于处理器的内存位置. 在NUMA下,处理器访问它自己的本地存储器的速度比非本地存储器(存储器的地方到另一个处理器之间共享的处理器或存储器)快一些. 针对NUMA架构系统的特点,可以通过将进程/线程

linux C守护进程编写

linux编程-守护进程编写 守护进程(Daemon)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待 处理某些发生的事件.守护进程是一种很有用的进程. Linux的大多数服务器就是用守护进程实现的.比如,Internet服务器inetd,Web服务器httpd等. 同时,守护进程完成许多系统任务.比如,作业规划进程crond,打印进程lpd等. 守护进程的编程本身并不复杂,复杂的是各种版本的Unix的实现机制不尽相同, 造成不同 Unix环境下守护进程的编程规则并不一