基本概念

cpu亲和性(affinity)

CPU的亲和性, 就是进程要在指定的 CPU 上尽量长时间地运行而不被迁移到其他处理器,也称为CPU关联性;再简单的点的描述就将指定的进程或线程绑定到相应的cpu上;在多核运行的机器上,每个CPU本身自己会有缓存,缓存着进程使用的信息,而进程可能会被OS调度到其他CPU上,如此,CPU cache命中率就低了,当绑定CPU后,程序就会一直在指定的cpu跑,不会由操作系统调度到其他CPU上,性能有一定的提高。

软亲和性(affinity)

就是进程要在指定的 CPU 上尽量长时间地运行而不被迁移到其他处理器,Linux 内核进程调度器天生就具有被称为 软 CPU 亲和性(affinity) 的特性,这意味着进程通常不会在处理器之间频繁迁移。这种状态正是我们希望的,因为进程迁移的频率小就意味着产生的负载小。

硬亲和性(affinity)

简单来说就是利用linux内核提供给用户的API,强行将进程或者线程绑定到某一个指定的cpu核运行。

相关函数

void CPU_ZERO (cpu_set_t *set)  /*这个宏对 CPU 集 set 进行初始化,将其设置为空集。*/
void CPU_SET (int cpu, cpu_set_t *set)  /*这个宏将 指定的 cpu 加入 CPU 集 set 中*/
void CPU_CLR (int cpu, cpu_set_t *set)  /*这个宏将 指定的 cpu 从 CPU 集 set 中删除。*/
int CPU_ISSET (int cpu, const cpu_set_t *set)  /*如果 cpu 是 CPU 集 set 的一员,这个宏就返回一个非零值(true),否则就返回零(false)。*/

进程与cpu的绑定

#include <sched.h>

int sched_setaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *mask);
int sched_getaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *mask);

代码示例:

#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h> /* sysconf( _SC_NPROCESSORS_CONF ) 查看cpu的个数;打印用%ld长整。
* sysconf( _SC_NPROCESSORS_ONLN ) 查看在使用的cpu个数;打印用%ld长整 */
int main(int argc, char **argv)
{
int cpus = 0;
int i = 0;
cpu_set_t mask;
cpu_set_t get; cpus = sysconf(_SC_NPROCESSORS_CONF);
printf("cpus: %d\n", cpus); CPU_ZERO(&mask); /* 初始化set集,将set置为空*/
CPU_SET(0, &mask); /* 依次将0、1、2、3号cpu加入到集合,前提是你的机器是多核处理器*/
CPU_SET(1, &mask);
CPU_SET(2, &mask);
CPU_SET(3, &mask); /*设置cpu 亲和性(affinity)*/
if (sched_setaffinity(0, sizeof(mask), &mask) == -1) {
printf("Set CPU affinity failue, ERROR:%s\n", strerror(errno));
return -1;
}
usleep(1000); /* 让当前的设置有足够时间生效*/ /*查看当前进程的cpu 亲和性*/
CPU_ZERO(&get);
if (sched_getaffinity(0, sizeof(get), &get) == -1) {
printf("get CPU affinity failue, ERROR:%s\n", strerror(errno));
return -1;
} /*查看运行在当前进程的cpu*/
for(i = 0; i < cpus; i++) { if (CPU_ISSET(i, &get)) { /*查看cpu i 是否在get 集合当中*/
printf("this process %d of running processor: %d\n", getpid(), i);
}
}
sleep(10); //让程序停在这儿,方便top命令查看 return 0;
}

结果:

线程与cpu的绑定

#include <pthread.h>

int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize, const cpu_set_t *cpuset);
int pthread_getaffinity_np(pthread_t thread, size_t cpusetsize, const cpu_set_t *cpuset);

代码示例:

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sched.h> void *testfunc(void *arg)
{
int i, cpus = 0;
cpu_set_t mask;
cpu_set_t get; cpus = sysconf(_SC_NPROCESSORS_CONF);
printf("this system has %d processor(s)\n", cpus); CPU_ZERO(&mask);
for (i = 0; i < 4; i++) { /*将0、1、2、3添加到集合中*/
CPU_SET(i, &mask);
} /* 设置cpu 亲和性(affinity)*/
if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0) {
fprintf(stderr, "set thread affinity failed\n");
} /* 查看cpu 亲和性(affinity)*/
CPU_ZERO(&get);
if (pthread_getaffinity_np(pthread_self(), sizeof(get), &get) < 0) {
fprintf(stderr, "get thread affinity failed\n");
} /* 查看当前线程所运行的所有cpu*/
for (i = 0; i < cpus; i++) {
if (CPU_ISSET(i, &get)) {
printf("this thread %d is running in processor %d\n", (int)pthread_self(), i);
}
}
sleep(3); //查看 pthread_exit(NULL);
} int main(int argc, char *argv[])
{
pthread_t tid;
if (pthread_create(&tid, NULL, (void *)testfunc, NULL) != 0) {
fprintf(stderr, "thread create failed\n");
return -1;
} pthread_join(tid, NULL);
return 0;
}

结果:

指定在哪个CPU上运行:

void *threadfunc(void *arg)
{
cpu_set_t mask; cpu_set_t mask;
int cpuid = 1;
CPU_ZERO(&mask);
CPU_SET(cpuid, &mask); /* 设置cpu 亲和性(affinity)*/
if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0) {
fprintf(stderr, "set thread affinity failed\n");
}
}

linux 将进程或者线程绑定到指定的cpu上的更多相关文章

  1. Linux进程或线程绑定到CPU

    Linux进程或线程绑定到CPU 为了让程序拥有更好的性能,有时候需要将进程或线程绑定到特定的CPU,这样可以减少调度的开销和保护关键进程或线程. 进程绑定到CPU Linux提供一个接口,可以将进程 ...

  2. Linux 进程、线程运行在指定CPU核上

    /******************************************************************************** * Linux 进程.线程运行在指定 ...

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

    =============================================================== linux下的单进程多线程的程序,要实现每个线程平均分配到多核cpu,主 ...

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

    本文首发:https://www.somata.work/2019/WindowsThreadBind.html 将线程绑定至指定CPU,这个应该时很多管理员需要了解认知的操作了吧,这样可以在一定程度 ...

  5. 理解Linux的进程,线程,PID,LWP,TID,TGID

    在Linux的top和ps命令中,默认看到最多的是pid (process ID),也许你也能看到lwp (thread ID)和tgid (thread group ID for the threa ...

  6. linux 下 进程和线程的区别

    1.进程与线程 进程是程序执行时的一个实例,即它是程序已经执行到课中程度的数据结构的汇集.从内核的观点看,进程的目的就是担当分配系统资源(CPU时间.内存等)的基本单位. 线程是进程的一个执行流,是C ...

  7. 深入理解 Linux的进程,线程,PID,LWP,TID,TGID

    转载:https://www.linuxidc.com/Linux/2019-03/157819.htm 在Linux的top和ps命令中,默认看到最多的是pid (process ID),也许你也能 ...

  8. [转载]了解Linux的进程与线程

    本文转自Tim Yang的博客http://timyang.net/linux/linux-process/ .对于理解Linux的进程与线程非常有帮助.支持原创.尊重原创,分享知识! 上周碰到部署在 ...

  9. [转] linux 下 进程和线程的区别

    1.进程与线程 进程是程序执行时的一个实例,即它是程序已经执行到课中程度的数据结构的汇集.从内核的观点看,进程的目的就是担当分配系统资源(CPU时间.内存等)的基本单位. 线程是进程的一个执行流,是C ...

随机推荐

  1. Python爬虫进阶五之多线程的用法

    前言 我们之前写的爬虫都是单个线程的?这怎么够?一旦一个地方卡到不动了,那不就永远等待下去了?为此我们可以使用多线程或者多进程来处理. 首先声明一点! 多线程和多进程是不一样的!一个是 thread ...

  2. Java程序设计17——多线程-Part-B

    5 改变线程优先级 每个线程执行都具有一定的优先级,优先级高的线程获得较多的执行机会,而优先级低的线程则获得较少的执行机会. 每个线程默认的优先级都与创建它的父线程具有相同的优先级,在默认情况下,ma ...

  3. html符号转换

    通常情况下,HTML会自动截去多余的空格.不管你加多少空格,都被看做一个空格.比如你在两个字之间加了10个空格,HTML会截去9个空格,只保留一个.为了在网页中增加空格,你可以使用 表示空格.最常用的 ...

  4. 【分享】Java后台开发精选知识图谱

    地址 引言: 学习一个新的技术时,其实不在于跟着某个教程敲出了几行.几百行代码,这样你最多只能知其然而不知其所以然,进步缓慢且深度有限,最重要的是一开始就对整个学习路线有宏观.简洁的认识,确定大的学习 ...

  5. python之使用API(WEB应用编程接口)

    1.处理API响应 import requests #执行API调用并存储响应 url = "https://api.github.com/search/repositories?q=lan ...

  6. (广搜)可口可乐 -- hdu -- 1495

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=1495 Time Limit: 2000/1000 MS (Java/Others)    Memory ...

  7. android虚拟机的垃圾收集

    Dalvik :http://zh.wikipedia.org/wiki/Dalvik%E8%99%9A%E6%8B%9F%E6%9C%BA ART :http://source.android.co ...

  8. NETSH.EXE操作SSL

    NETSH.EXE操作SSL 程序位置:c:\windows\syswow64\netsh.exe 查看当前端口配置 netsh http show sslcert 将 SSL 证书绑定至端口号 ne ...

  9. Android-自定义控件之事件分发

    最大范围 外层蓝色区域是继承ViewGroup 中间红色区域,也是继承ViewGroup 最中间黑色区域,是继承View 布局相关的代码: <!-- 事件分发 --> <view.c ...

  10. 基于Extjs的web表单设计器 第二节——表单控件设计

    这一节介绍表单设计器的常用控件的设计. 在前面两章节的附图中我已经给出了表单控件的两大分类:区域控件.常用控件.这里对每个分类以及分类所包含的控件的作用进行一一的介绍,因为它们很重要,是表单设计器的基 ...