您的位置 首页 > 德语词汇

affinity是什么意思?用法、例句,Linux中CPU亲和性(affinity)

各位老铁们,大家好,今天由我来为大家分享affinity是什么意思?用法、例句,以及Linux中CPU亲和性(affinity)的相关问题知识,希望对大家有所帮助。如果可以帮助到大家,还望关注收藏下本站,您的支持是我们最大的动力,谢谢大家了哈,下面我们开始吧!

affinity是什么意思?用法、例句,Linux中CPU亲和性(affinity)

今天来聊聊亲和力,在这之前我们想比都听说过超线程。

超线程技术(Hyper-Threading):就是利用特殊的硬件指令,把两个逻辑内核(CPUcore)模拟成两个物理芯片,(一个核模拟出两个核?)

尽管提高CPU的时钟频率和增加缓存容量后的确可以改善CPU性能,但这样的CPU性能提高在技术上存在较大的难度。实际上在应用中基于很多原因,CPU的执行单元都没有被充分使用。如果CPU不能正常读取数据(总线/内存的瓶颈),其执行单元利用率会明显下降。另外就是目前大多数执行线程缺乏ILP(Instruction-LevelParallelism,多种指令同时执行)支持。这些都造成了目前CPU的性能没有得到全部的发挥。

因此,Intel则采用另一个思路去提高CPU的性能,让CPU可以同时执行多重线程,就能够让CPU发挥更大效率,即所谓“超线程(Hyper-Threading,简称“HT”)”技术。超线程技术就是利用特殊的硬件指令,把两个逻辑内核模拟成两个物理芯片,让单个处理器都能使用线程级并行计算,进而兼容多线程操作系统和软件,减少了CPU的闲置时间,提高的CPU的运行效率。

?物理内核:嵌在cpu芯片上的处理器,一个cpu可以有多个内核,其id都不一样

?逻辑内核:通过超线程技术,能将一个物理核分成多个逻辑核,也就是代码层面的多线程技术

让单个处理器都能使用线程级并行计算,进而兼容多线程操作系统和软件,减少了CPU的闲置时间,提高的CPU的运行效率。

我们常听到的双核四线程/四核八线程指的就是支持超线程技术的CPU.

物理CPU:机器上安装的实际CPU,比如说你的主板上安装了一个8核CPU,那么物理CPU个数就是1个,所以物理CPU个数就是主板上安装的CPU个数。

逻辑CPU:一般情况,我们认为一颗CPU可以有多核,加上intel的超线程技术(HT),可以在逻辑上再分一倍数量的CPUcore出来;

逻辑CPU数量=物理CPU数量xCPUcoresx2(如果支持并开启HT)

前提是CPU的型号一致,如果不一致只能一个一个的加起来,不用直接乘以物理CPU数量

比如你的电脑安装了一块4核CPU,并且支持且开启了超线程(HT)技术,那么逻辑CPU数量=1×4×2=8

?Linux下查看CPU相关信息,CPU的信息主要都在/proc/cupinfo中,

#查看物理CPU个数cat/proc/cpuinfo|grep"physicalid"|sort-u|wc-l#查看每个物理CPU中core的个数(即核数)cat/proc/cpuinfo|grep"cpucores"|uniq#查看逻辑CPU的个数cat/proc/cpuinfo|grep"processor"|wc-l#查看CPU的名称型号cat/proc/cpuinfo|grep"name"|cut-f2-d:|uniq

?Linux查看某个进程运行在哪个逻辑CPU上ps-eopid,args,psr#参数的含义:pid-进程IDargs-该进程执行时传入的命令行参数psr-分配给进程的逻辑CPU例子:[~]#ps-eopid,args,psr|grepnginx9073nginx:masterprocess/usr/19074nginx:workerprocess09075nginx:workerprocess19076nginx:workerprocess29077nginx:workerprocess313857grepnginx3

?TID就是ThreadID,他和POSIX中pthread_t表示的线程ID完全不是同一个东西.

?Linux中的POSIX线程库实现的线程其实也是一个轻量级进程(LWP),这个TID就是这个线程的真实PID.

?但是又不能通过getpid()函数获取,Linux中定义了gettid()这个接口,但是通常都是未实现的,所以需要使用下面的方式获取TID。

//program#include<sys/syscall.h>pid_ttid;tid=syscall(__NR_gettid);//orsyscall(SYS_gettid)//command-line3种方法(推荐第三种方法)(1)ps-efL|grepprog_name(2)ls/proc/pid/task//文件夹名即TID(3)ps-To'pid,lwp,psr,cmd'-pPID

基于上述背景之下,我们来学习一下什么是CPU亲和力

CPUaffinity是一种调度属性(schedulerproperty),它可以将一个进程"绑定"到一个或一组CPU上.

在SMP(SymmetricMulti-Processing对称多处理)架构下,Linux调度器(scheduler)会根据CPUaffinity的设置让指定的进程运行在"绑定"的CPU上,而不会在别的CPU上运行.

Linux调度器同样支持自然CPU亲和性(naturalCPUaffinity):调度器会试图保持进程在相同的CPU上运行,这意味着进程通常不会在处理器之间频繁迁移,进程迁移的频率小就意味着产生的负载小。

因为程序的作者比调度器更了解程序,所以我们可以手动地为其分配CPU核,而不会过多地占用CPU0,或是让我们关键进程和一堆别的进程挤在一起,所有设置CPU亲和性可以使某些程序提高性能。

CPUaffinity使用位掩码(bitmask)表示,每一位都表示一个CPU,置1表示"绑定".

最低位表示第一个逻辑CPU,最高位表示最后一个逻辑CPU.

CPUaffinity典型的表示方法是使用16进制,具体如下.

0x00000001isprocessor#00x00000003isprocessors#0and#10xFFFFFFFFisallprocessors(#0through#31)taskset命令

taskset命名用于获取或者设定CPU亲和性.

#命令行形式taskset[options]maskcommand[arg]...taskset[options]-p[mask]pidPARAMETERmask:cpu亲和性,当没有-c选项时,其值前无论有没有0x标记都是16进制的,当有-c选项时,其值是十进制的.command:命令或者可执行程序arg:command的参数pid:进程ID,可以通过ps/top/pidof等命令获取OPTIONS-a,--all-tasks(旧版本中没有这个选项)这个选项涉及到了linux中TID的概念,他会将一个进程中所有的TID都执行一次CPU亲和性设置.TID就是ThreadID,他和POSIX中pthread_t表示的线程ID完全不是同一个东西.Linux中的POSIX线程库实现的线程其实也是一个进程(LWP),这个TID就是这个线程的真实PID.-p,--pid操作已存在的PID,而不是加载一个新的程序-c,--cpu-list声明CPU的亲和力使用数字表示而不是用位掩码表示.例如0,5,7,9-11.-h,--helpdisplayusageinformationandexit-V,--versionoutputversioninformationandexitUSAGE1)使用指定的CPU亲和性运行一个新程序taskset[-c]maskcommand[arg]...举例:使用CPU0运行ls命令显示/etc/init.d下的所有内容taskset-c0ls-al/etc/init.d/2)显示已经运行的进程的CPU亲和性taskset-ppid举例:查看init进程(PID=1)的CPU亲和性taskset-p13)改变已经运行进程的CPU亲和力taskset-p[c]maskpid举例:打开2个终端,在第一个终端运行top命令,第二个终端中首先运行:[~]#ps-eopid,args,psr|greptop#获取top命令的pid和其所运行的CPU号其次运行:[~]#taskset-cp新的CPU号pid#更改top命令运行的CPU号最后运行:[~]#ps-eopid,args,psr|greptop#查看是否更改成功PERMISSIONS一个用户要设定一个进程的CPU亲和性,如果目标进程是该用户的,则可以设置,如果是其他用户的,则会设置失败,提示Operationnotpermitted.当然root用户没有任何限制.任何用户都可以获取任意一个进程的CPU亲和性.

taskset命令其实就是使用sched_getaffinity()和sched_setaffinity()接口实现的,相信看完了第3节你也能自己实现一个taskset命令.

有兴趣的可以看一下其源代码:ftp://ftp.kernel.org/pub/linux/utils/util-linux/vX.YZ/util-linux-X.YZ-xxx.tar.gz/schedutils/taskset.c

下面是用用于设置和获取CPU亲和性相关的API.

#define_GNU_SOURCE#include<sched.h>#include<pthread.h>//forpthreadfunctions(last4)注意<pthread.h>包含<sched.h>/*MACRO*//*ThefollowingmacrosareprovidedtooperateontheCPUsetset*//*Clearsset,sothatitcontainsnoCPUs*/voidCPU_ZERO(cpu_set_t*set);voidCPU_ZERO_S(size_tsetsize,cpu_set_t*set);/*AddCPUcputoset*/voidCPU_SET(intcpu,cpu_set_t*set);voidCPU_SET_S(intcpu,size_tsetsize,cpu_set_t*set);/*RemoveCPUcpufromset*/voidCPU_CLR(intcpu,cpu_set_t*set);voidCPU_CLR_S(intcpu,size_tsetsize,cpu_set_t*set);/*TesttoseeifCPUcpuisamemberofset*/intCPU_ISSET(intcpu,cpu_set_t*set);intCPU_ISSET_S(intcpu,size_tsetsize,cpu_set_t*set);/*ReturnthenumberofCPUsinset*/voidCPU_COUNT(cpu_set_t*set);voidCPU_COUNT_S(size_tsetsize,cpu_set_t*set);/*ThefollowingmacrosperformlogicaloperationsonCPUsets*//*StorethelogicalANDofthesetssrcset1andsrcset2indestset(whichmaybeoneofthesourcesets).*/voidCPU_AND(cpu_set_t*destset,cpu_set_t*srcset1,cpu_set_t*srcset2);voidCPU_AND_S(size_tsetsize,cpu_set_t*destset,cpu_set_t*srcset1,cpu_set_t*srcset2);/*StorethelogicalORofthesetssrcset1andsrcset2indestset(whichmaybeoneofthesourcesets).*/voidCPU_OR(cpu_set_t*destset,cpu_set_t*srcset1,cpu_set_t*srcset2);voidCPU_OR_S(size_tsetsize,cpu_set_t*destset,cpu_set_t*srcset1,cpu_set_t*srcset2);/*StorethelogicalXORofthesetssrcset1andsrcset2indestset(whichmaybeoneofthesourcesets).*/voidCPU_XOR(cpu_set_t*destset,cpu_set_t*srcset1,cpu_set_t*srcset2);voidCPU_XOR_S(size_tsetsize,cpu_set_t*destset,cpu_set_t*srcset1,cpu_set_t*srcset2);/*TestwhethertwoCPUsetcontainexactlythesameCPUs.*/intCPU_EQUAL(cpu_set_t*set1,cpu_set_t*set2);intCPU_EQUAL_S(size_tsetsize,cpu_set_t*set1,cpu_set_t*set2);/*ThefollowingmacrosareusedtoallocateanddeallocateCPUsets:*//*AllocateaCPUsetlargeenoughtoholdCPUsintherange0tonum_cpus-1*/cpu_set_t*CPU_ALLOC(intnum_cpus);/*ReturnthesizeinbytesoftheCPUsetthatwouldbeneededtoholdCPUsintherange0tonum_cpus-1.ThismacroprovidesthevaluethatcanbeusedforthesetsizeargumentintheCPU_*_S()macros*/size_tCPU_ALLOC_SIZE(intnum_cpus);/*FreeaCPUsetpreviouslyallocatedbyCPU_ALLOC().*/voidCPU_FREE(cpu_set_t*set);/*API*//*SettheCPUaffinityforatask*/intsched_setaffinity(pid_tpid,size_tcpusetsize,cpu_set_t*mask);/*GettheCPUaffinityforatask*/intsched_getaffinity(pid_tpid,size_tcpusetsize,cpu_set_t*mask);/*setCPUaffinityattributeinthreadattributesobject*/intpthread_attr_setaffinity_np(pthread_attr_t*attr,size_tcpusetsize,constcpu_set_t*cpuset);/*getCPUaffinityattributeinthreadattributesobject*/intpthread_attr_getaffinity_np(constpthread_attr_t*attr,size_tcpusetsize,cpu_set_t*cpuset);/*setCPUaffinityofathread*/intpthread_setaffinity_np(pthread_tthread,size_tcpusetsize,constcpu_set_t*cpuset);/*getCPUaffinityofathread*/intpthread_getaffinity_np(pthread_tthread,size_tcpusetsize,cpu_set_t*cpuset);

相关的宏通常都分为2种,一种是带_S后缀的,一种不是不带_S后缀的,从声明上看带_S后缀的宏都多出一个参数setsize.

从功能上看他们的区别是带_S后缀的宏是用于操作动态申请的CPUset(s),所谓的动态申请其实就是使用宏CPU_ALLOC申请,

参数setsize可以是通过宏CPU_ALLOC_SIZE获得,两者的用法详见下面的例子.

相关的API只有6个,前2个是用来设置进程的CPU亲和性,需要注意的一点是,当这2个API的第一个参数pid为0时,表示使用调用进程的进程ID;

后4个是用来设置线程的CPU亲和性。其实sched_setaffinity()也可以用来设置线程的CPU的亲和性,也就是taskset“-a”选项中提到的TID概念。

上次看见这个亲和力的这个词语是在系统的日志信息,还挺纳闷的这个是什么?绑定确实是一个不错的解释。感谢前辈的文章,原文还有四个栗子,这里就不贴出来了。需要了可以点击原文查看。

END,本文到此结束,如果可以帮助到大家,还望关注本站哦!

本站涵盖的内容、图片、视频等数据,部分未能与原作者取得联系。若涉及版权问题,请及时通知我们并提供相关证明材料,我们将及时予以删除!谢谢大家的理解与支持!

Copyright © 2023