CPU拓扑结构学习
前言
如果你也是对/proc/cpuinfo文件里面的内容不甚了解,请跟我一起来学习下CPU的拓扑结构 (CPU Topology)。我们先从一些简单的概念开始。
NUNA与SMP
NUMA(Non-Uniform Memory Access,非一致性内存访问)和SMP(Symmetric Multi-Processor,对称多处理器系统)是两种不同的CPU硬件体系架构。
SMP的主要特征是共享,所有的CPU共享使用全部资源,例如内存、总线和I/O,多个CPU对称工作,彼此之间没有主次之分,平等地访问共享的资源,这样势必引入资源的竞争问题,从而导致它的扩展内力非常有限。
NUMA技术将CPU划分成不同的组(Node),每个Node由多个CPU组成,并且有独立的本地内存、I/O等资源。Node之间通过互联模块连接和沟通,因此除了本地内存外,每个CPU仍可以访问远端Node的内存,只不过效率会比访问本地内存差一些,我们用Node之间的距离(Distance,抽象的概念)来定义各个Node之间互访资源的开销。
Node->Socket->Core->Processor
如果你只知道CPU这么一个概念,那么是无法理解CPU的拓扑的。事实上,在NUMA架构下,CPU的概念从大到小依次是:Node、Socket、Core、Processor。Node的概念在上一节已经介绍过,这里就不多赘述了。
随着多核技术的发展,我们将多个CPU封装在一起,这个封装一般被称为Socket(插槽的意思,也有人称之为Packet,不知到哪个更加准确?),而Socket中的每个核心被称为Core。为了进一步提升CPU的处理能力,Intel又引入了HT(Hyper-Threading,超线程)的技术,一个Core打开HT之后,在OS看来就是两个核,当然这个核是逻辑上的概念,所以也被称为Logical Processor,本文简称为Processor。
综上所述,一个NUMA Node可以有一个或者多个Socket,一个多核Socket显然包含多个Core,一个Core如果打开HT则变成两个Logical Processor。Logical processor只是OS内部看到的,实际上两个Processor还是位于同一个Core上,所以频繁的调度仍可能导致资源竞争,影响性能。
查看 CPU Topology
在介绍完CPU拓扑相关的概念后,我们来实际在服务器上查看相关的信息。
查看Numa Node
numactl是设定进程NUMA策略的命令行工具,也可以用来查看当前的Nuwa node:
$ numactl --hardware
available: 2 nodes (0-1)
node 0 size: 24211 MB
node 0 free: 110 MB
node 1 size: 24240 MB
node 1 free: 150 MB
node distances: node 0 1
0: 10 20
1: 20 10
从上面可以看出本机有两个Numa node,如果要进一步知道一个Node包含哪几个CPU,该怎么办?
一种方法是通过查看ls /sys/devices/system/node/目录下的信息,例如:
[admin@AY41A_AG]$ ls /sys/devices/system/node/node0
cpu12 cpu13 cpu14 cpu15 cpu4 cpu5 cpu6 cpu7 cpumap distance meminfo numastat
可见, node0包含4/5/6/7/12/13/14/15八个Processor(刚好是一个Socket)。
如果是xen的环境,还可以通过xm info来查看,对应的是node_to_cpu字段。
查看Socket
一个Socket对应主板上的一个插槽,在本文中是指一个CPU封装。在/proc/cpuinfo中的physical id就是Socket的ID,可以从中找到本机到底有多少个Socket,并且每个Socket有那几个Processor。
查看有几个Socket
$ grep 'physical id' /proc/cpuinfo | awk -F: '{print $2 | "sort -un"}'
0
1
$ grep 'physical id' /proc/cpuinfo | awk -F: '{print $2 | "sort -un"}' | wc -l
2
2) 查看每个Socket有几个Processor
$ grep 'physical id' /proc/cpuinfo | awk -F: '{print $2}' | sort | uniq -c 8 0 8 1
3) 查看Socket对应那几个Processor
$ awk -F: '{
if ($1 ~ /processor/) {
gsub(/ /,"",$2);
p_id=$2;
} else if ($1 ~ /physical id/){
gsub(/ /,"",$2);
s_id=$2;
arr[s_id]=arr[s_id] " " p_id
}
}
END{
for (i in arr)
print arr[i];
}' /proc/cpuinfo | cut -c2- 4 5 6 7 12 13 14 15 0 1 2 3 8 9 10 11
查看Core
/proc/cpuinfo文件中的cpu cores表明一个socket中有几个cores,例如:
cat /proc/cpuinfo | grep ‘core’ | sort -u
core id : 0 core id : 1 core id : 10 core id : 9 cpu cores : 4
上面的结果说明一个socket有4个cores,它们的id分别为0/1/9/10,根据之前查到的我们的机器有2个socket,所以总共有8个core。
查看Processor
查看Processors的个数就比较简单了,从上面的统计结果中我们已经可以知道有16个Logical processor,不过也可以直接从/proc/cpuinfo文件中获取:
$ grep 'processor' /proc/cpuinfo | wc -l 16
其实,每个socket中能有几个processor也可以从siblings字段中获取:
$ grep 'siblings' /proc/cpuinfo | sort -u siblings : 8
信息汇总
基于以上查看CPU拓扑信息的方法,简单的写了一个小程序来查询:
#!/bin/bash
# Simple print cpu topology
# Author: kodango
function get_nr_processor()
{
grep '^processor' /proc/cpuinfo | wc -l
}
function get_nr_socket()
{
grep 'physical id' /proc/cpuinfo | awk -F: '{ print $2 | "sort -un"}' | wc -l
}
function get_nr_siblings()
{
grep 'siblings' /proc/cpuinfo | awk -F: '{ print $2 | "sort -un"}'
}
function get_nr_cores_of_socket()
{
grep 'cpu cores' /proc/cpuinfo | awk -F: '{ print $2 | "sort -un"}'
}
echo '===== CPU Topology Table ====='
echo
echo '+--------------+---------+-----------+'
echo '| Processor ID | Core ID | Socket ID |'
echo '+--------------+---------+-----------+'
while read line; do
if [ -z "$line" ]; then
printf '| %-12s | %-7s | %-9s |\n' $p_id $c_id $s_id
echo '+--------------+---------+-----------+'
continue
fi
if echo "$line" | grep -q "^processor"; then
p_id=`echo "$line" | awk -F: '{print $2}' | tr -d ' '`
fi
if echo "$line" | grep -q "^core id"; then
c_id=`echo "$line" | awk -F: '{print $2}' | tr -d ' '`
fi
if echo "$line" | grep -q "^physical id"; then
s_id=`echo "$line" | awk -F: '{print $2}' | tr -d ' '`
fi
done < /proc/cpuinfo
echo
awk -F: '{ if ($1 ~ /processor/) { gsub(/ /,"",$2); p_id=$2; } else if ($1 ~ /physical id/){ gsub(/ /,"",$2); s_id=$2; arr[s_id]=arr[s_id] " " p_id } } END{ for (i in arr) printf "Socket %s:%s\n", i, arr[i]; }' /proc/cpuinfo
echo
echo '===== CPU Info Summary ====='
echo
nr_processor=`get_nr_processor`
echo "Logical processors: $nr_processor"
nr_socket=`get_nr_socket`
echo "Physical socket: $nr_socket"
nr_siblings=`get_nr_siblings`
echo "Siblings in one socket: $nr_siblings"
nr_cores=`get_nr_cores_of_socket`
echo "Cores in one socket: $nr_cores"
let nr_cores*=nr_socket
echo "Cores in total: $nr_cores"
if [ "$nr_cores" = "$nr_processor" ]; then
echo "Hyper-Threading: off"
else
echo "Hyper-Threading: on"
fi
echo
echo '===== END ====='
执行结果为:
===== CPU Topology Table =====
+--------------+---------+-----------+
| Processor ID | Core ID | Socket ID | +--------------+---------+-----------+
| 0 | 0 | 1 | +--------------+---------+-----------+
| 1 | 1 | 1 | +--------------+---------+-----------+
| 2 | 9 | 1 | +--------------+---------+-----------+
| 3 | 10 | 1 | +--------------+---------+-----------+
| 4 | 0 | 0 | +--------------+---------+-----------+
| 5 | 1 | 0 | +--------------+---------+-----------+
| 6 | 9 | 0 | +--------------+---------+-----------+
| 7 | 10 | 0 | +--------------+---------+-----------+
| 8 | 0 | 1 | +--------------+---------+-----------+
| 9 | 1 | 1 | +--------------+---------+-----------+
| 10 | 9 | 1 | +--------------+---------+-----------+
| 11 | 10 | 1 | +--------------+---------+-----------+
| 12 | 0 | 0 | +--------------+---------+-----------+
| 13 | 1 | 0 | +--------------+---------+-----------+
| 14 | 9 | 0 | +--------------+---------+-----------+
| 15 | 10 | 0 | +--------------+---------+-----------+
Socket 0: 4 5 6 7 12 13 14 15
Socket 1: 0 1 2 3 8 9 10 11
===== CPU Info Summary =====
Logical processors: 16
Physical socket: 2
Siblings in one socket: 8
Cores in one socket: 4
Cores in total: 8
Hyper-Threading: on
===== END =====
参考资料
- SMP、NUMA、MPP体系结构介绍 - victoryubo - 博客园
- 玩转CPU Topology(推荐阅读)
figuring out cpu topology in oracle vm (Wim Coekaerts Blog)
相关文章
- 恶补web之三:http学习
- Knockout.Js官网学习(options绑定)
- Excel函数学习:HLOOKUP函数
- Java -- JDBC 学习--PreparedStatement
- haproxy学习之手机规则匹配
- 【NLP】蓦然回首:谈谈学习模型的评估系列文章(二)
- Spartacussampledataaddon AddOn学习笔记
- Atitit 计算机系统结构 计算机系统结构 Cpu 存储 cache 指令系统 目录 Line 56: 第2章指令系统设计 指令格式 寻址方式1 Line 64: 第3章CPU及其实现
- Java学习之路 之 注意篇
- 学习python第一天,请教一下怎么学?
- 机器学习、数据挖掘和统计模式识别学习(Matlab代码实现)
- 机器学习(四十七):万字可视化终极篇
- 数学建模学习(40):三维曲线(非线性)拟合
- Python学习28:map/reduce
- R0-R37它是Arm 寄存器,那是,CPU内部。和GPIO注册所有外设。换句话说,要是arm的cpu,它包含了其他芯片公司将有R0-R37,和GPIO寄存器只有一个特定的芯片。
- 记录真实想法,在路上不断前行——关于工作,学习,职场
- linux达人养成计划学习笔记(二)—— 文件查找命令
- I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2
- 爬虫学习之-操作mysql
- 学习目录-自己动手写CPU
- DL+ML集成学习--附思维导图
- Linux:Security: random: RANDOM_TRUST_CPU;random.trust_cpu;entropy;随机熵