下图展示了这些术语之间的逻辑关系:
一个NUMA node包括一个或者多个Socket,以及与之相连的local memory。一个多核的Socket有多个Core。如果CPU支持HT,OS还会把这个Core看成 2个Logical Processor。为了避免混淆,在下文中统一用socket指代Processor or Socket;为了偷懒,下文中用Processor指代Logical Processor,击键能省则省不是。
查看CPU Topology
本文以笔者能访问的某台Red Hat Enterprise Linux Server release 5.4为例介绍,其他系统请自行google。
NUMA Node
第一种方法使用numactl查看
numactl –hardware
1
2
3
4
5
6
7
8
9
|
available: 2 nodes (0-1) //当前机器有2个NUMA node,编号0&1
node 0 size: 12091 MB //node 0 物理内存大小
node 0 free : 988 MB //node 0 当前free内存大小
node 1 size: 12120 MB node 1 free : 1206 MB
node distances: //node 距离,可以简单认为是CPU本node内存访问和跨node内存访问的成本。从下表可知跨node的内存访问成本(20)是本地node内存(10)的2倍。
node 0 1 0: 10 20
1: 20 10
|
第二种方法是通过sysfs查看,这种方式可以查看到更多的信息
ls /sys/devices/system/node/
1
|
node0 node1 //两个目标表示本机有2个node,每个目录内部有多个文件和子目录描述node内cpu,内存等信息。比如说node0/meminfo描述了node0内存相关信息。
|
Socket
可以直接通过/proc/cpuinfo查看,cpuinfo里的physical id描述的就是Socket的编号,
cat /proc/cpuinfo|grep “physical id”
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
] physical id : 0 physical id : 0 physical id : 0 physical id : 0 physical id : 1 physical id : 1 physical id : 1 physical id : 1 physical id : 0 physical id : 0 physical id : 0 physical id : 0 physical id : 1 physical id : 1 physical id : 1 physical id : 1 |
由上可知本机有2个Socket,编号为0和1。
还可以简单的使用如下命令直接查看Socket个数
cat /proc/cpuinfo|grep “physical id”|sort -u|wc –l
1
|
2 //本机有2个物理CPU封装
|
Core
仍然是可以通过/proc/cpuinfo查看,cpuinfo中跟core相关的信息有2行。
cpu cores : 4 //一个socket有4个核,
core id : 1 //一个core在socket内的编号
通过如下命令可以直接查看core的数量
cat /proc/cpuinfo |grep “cpu cores”|uniq|cut -d: -f2
1
|
4 //1个socket有4个core
|
本机有2个socket,每个有4个core,所以一共有8个core
还可以查看core在Socket里的编号
cat /proc/cpuinfo|grep “core id”|sort -u
1
2
3
4
|
core id : 0 core id : 1 core id : 10 core id : 9 |
一个socket里面4个core的编号为0,1,9,10。是的,core id是不连续的。如果谁知道为啥麻烦通知我,先谢了。
Logical Processor
仍然是可以通过/proc/cpuinfo查看在OS的眼里有多少个Logical Processor
ls /sys/devices/system/cpu/cpu0/cache/
1
|
index0 index1 index2 index3 |
4个目录
index0:1级数据cache
index1:1级指令cache
index2:2级cache
index3:3级cache ,对应cpuinfo里的cache
目录里的文件是cache信息描述,以本机的cpu0/index0为例简单解释一下:
文件 | 内容 | 说明 |
type | Data | 数据cache,如果查看index1就是Instruction |
Level | 1 | L1 |
Size | 32K | 大小为32K |
coherency_line_size | 64 | 64*4*128=32K|
physical_line_partition | 1 | |
ways_of_associativity | 4 | |
number_of_sets | 128 | |
shared_cpu_map | 00000101 | 表示这个cache被CPU0和CPU8 share |
解释一下shared_cpu_map内容的格式:
表面上看是2进制,其实是16进制表示,每个bit表示一个cpu,1个数字可以表示4个cpu
截取00000101的后4位,转换为2进制表示
CPU id | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0×0101的2进制表示 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
0101表示cpu8和cpu0,即cpu0的L1 data cache是和cpu8共享的。
验证一下?
cat /sys/devices/system/cpu/cpu8/cache/index0/shared_cpu_map
00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000101
再看一下index3 shared_cpu_map的例子
cat /sys/devices/system/cpu/cpu0/cache/index3/shared_cpu_map
00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000f0f
CPU id | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0x0f0f的2进制表示 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 |
cpu0,1,2,3和cpu8,9,10,11共享L3 cache
小结
抱歉,图比较大,网页上看不清楚,下面放大单node图,另一个node基本上可以类推。
使用CPU Topology
好吧,现在我们知道了如何查看CPU topology。那么这与各位攻城狮的工作有什么关系呢?
以淘宝搜索常见的服务模型为例,服务端把离线处理的数据load到内存中,开始监听某个服务端口,接收到客户端请求后从线程池中分配一个工作线程,该线程解析请求,读取内存中对应的数据,进行一些计算,然后把结果返回给客户端。
把这个过程简化简化再简化,抽象抽象再抽象,可以得到一个简单的测试程序,程序流程为:
1. 主线程申请2块256M的内存,使用memset初始化这两块内存的每个byte
2. 启动2个子线程,每个线程内循环16M次,在每次循环中随机读取2块内存中的各1K数据,对每个byte进行简单加和,返回。
3. 主线程等待子线程结束,打印每个线程的结果,结束。
使用-O2编译出可执行文件test,分别使用下面2个命令运行该程序。运行时间和机器配置以及当前load有关,绝对值没有意义,这里仅比较相对值。
命令 | time ./test | time numactl -m 0 –physcpubind=2,3 ./test |
用时 |
real 0m38.678s user 1m6.270s sys 0m5.569s |
real 0m28.410s user 0m54.997s sys 0m0.961s |
发生了什么?为什么有这么大的差异?
第一个命令直观,那么我们看一下第二个命令具体做了什么:
numactl -m 0 –physcpubind=2,3 ./test
-m 0:在node 0上分配内存
–physcpubind=2,3:在cpu 2和3上运行程序,即一个线程运行在cpu2上,另一个运行在cpu3上。
参考上面的CPUtopology图就很容易理解了,由于线程绑定cpu2和3执行,共享了L3 cache,且全部内存都是本node访问,运行效率自然比随机选择cpu运行,运行中还有可能切换cpu,内存访问有可能跨node的第一种方式要快了。
接下来,让我们看看完整的表格,读者可以看看有没有惊喜:
情况 | 命令 | 用时 | 解释 |
完全由OS控制 | time ./test | real 0m38.678s user 1m6.270s sys 0m5.569s |
乐观主义者,甩手掌柜型 |
绑定跨node的Cpu执行 | time numactl –physcpubind=2,6 ./test | real 0m38.657s user 1m7.126s sys 0m5.045s |
Cpu 2和6不在同一个node,不能share L3 cache |
绑定单node的Cpu执行 | time numactl –physcpubind=2,3 ./test | real 0m28.605s user 0m55.161s sys 0m0.856s |
Cpu 2和3在同一个node,share L3 cache。内存使用由OS控制,一般来说node 0和1内存都会使用。 |
跨node内存访问+绑定单node CPU执行 | time numactl -m 1 –physcpubind=2,3 ./test | real 0m33.218s user 1m4.494s sys 0m0.911s |
内存全使用node1,2个cpu在node0,内存访问比较吃亏 |
单node内存访问+绑定本node CPU执行 | time numactl -m 0 –physcpubind=2,3 ./test | real 0m28.367s user 0m55.062s sys 0m0.825s |
内存&cpu都使用node0 |
单node内存访问+绑定本node 单core执行 | time numactl -m 0 –physcpubind=2,10 ./test | real 0m58.062s user 1m55.520s sys 0m0.270s |
CPU2和10不但在同一个node,且在同一个core,本意是希望共享L1,L2cache,提升性能。但是不要忘了,CPU2和10是HT出来的logical Processor,在本例cpu密集型的线程中硬件争用严重,效率急剧下降。有没有发现和上一个case的时间比率很有意思? |
现在谁还能说了解点cpu topology没用呢?☺
Tips
补充几个小tips,方便有兴趣的同学分析上面表格的各个case
1.查看进程的内存numa node分布
简单的说可以查看进程的numa_maps文件
cat /proc//numa_maps
文件格式可以直接:man numa_maps
为了避免输入数字pid,我使用如下命令查看:
cat /proc/$(pidof test|cut –d” ” -f1)/numa_maps
2.查看线程run在哪个processor
可以使用top命令查看一个进程的各个线程分别run在哪个processor上
同样,为了避免输入数字pid,我使用如下命令启动top:
top -p$(pidof test |sed -e ‘s/ /,/g’)
在默认配置下不显示线程信息,需要进入Top后按“shift+H”,打开线程显示。
另外,如果没有P列,还需要按“f”,按“j”,添加,这一列显示的数字就是这个线程上次run的processor id。
关于top的使用,请读者自行man top
3.另一种绑定cpu执行的方法
如果读者的程序不涉及大量内存的访问,可以通过taskset绑定cpu执行。别怪我没提醒你,仔细判断是否应该绑定到同一个core的processor上哦。
关于命令的使用,请读者自行Man taskset
相关推荐
对称多处理器系统CPU转换机制研究.pdf
今天小编就为大家分享一篇将Pytorch模型从CPU转换成GPU的实现方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
Figure out if your node process is blocked because the CPU is spinning and exit the program with a stack trace if that is the case
INTEL 7代CPU安装WIN7集成显卡驱动,新电脑安装WIN7头疼的使用这个。
操作系统概论复习大纲,每个章节的重点知识以及各种例题
逻辑电路设计、真值表、k-map。cpu设计、pipeline。single cycle cpu转multi-cycle cpu
FRABA 绝对旋转式编码器 示例项目(CPU 315 )zip,FRABA 绝对旋转式编码器 示例项目(CPU 315 )
在“Linux CPU core的电源管理(1)_概述”中,我们多次提到SMP、CPU core等概念,虽然硬着头皮写下去了,但是蜗蜗对这些概念总有些似懂非懂的感觉。它们和CPU的进化过程息息相关,最终会体现在CPU topology(拓扑结构...
西门子如何转换S7-1200 CPU模拟量zip,西门子如何转换S7-1200 CPU模拟量
该CPU采用8位地址总线,每个进程拥有128K地址空间,其中包括32个2K的数据页和32个2K的代码页,这些地址影射到22位的物理地址空间中,如果算上外部设备的地址空间就是23位物理地址空间。 怎么样?够强的吧?这还...
用CPU实现角度旋转
这是基于libvlc设计视频播放器,这是可执行文件,不是源码。可以体验视频的CPU和GPU占用率情况。 支持3种解码渲染方式: 1. GPU硬件解码硬件渲染; 2. GPU解码,CPU渲染; 3. CPU解码,CPU渲染。
请你设计一种先进的计算机体系结构,它使用硬件而不是中断来完成进程切换,则CPU需要哪些信息?请描述用硬件完成进程切换的工作过程。 答:该计算机有一个专用硬件寄存器,它始终存放指向当前运行进程的PCB的指针.当...
主板与CPU的搭配 主板 2008-10-24 21:09:32 阅读672 评论0 字号:大中小 订阅 我们都知道,内存的多少对系统的速度有很大的影响,增加内存成为系统升级的首选,很多用户都想为自己的爱机增加内存。内存容量当然是...
如何转换S7-1200 CPU模拟量 问题:在S7-1200 CPU中,如何实现模拟量数值与工程量数值之间的转换? 回答:本文档提供了程序库例程FC105,FC106,用户可以使用它们将模拟量输入/输出的整数数值与工程量单位之间进行转换...
CPU资源占用100%解决方法
一个gpu实现图像快速旋转的综述文章,摘自于期刊
2017年4月26日全新打包的webp格式转换库,支持的android6.0以上,可以直接用,使用方法我再博客里会说明
初始状态下计时器显示00.00,当按下S2键时,外部中断 INT1向CPU发出中断请求,CPU转去执行外部中断1服务程序,即开启定时器。计时采用定 时器T中断完成,秒表要求的精度为0.01秒,故设定定时溢出中断周期为10ms,当...