NUNA与SMP

来源:互联网 发布:ajax上传文件到阿里云 编辑:程序博客网 时间:2024/06/04 20:01


出处:http://kodango.com/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 --hardwareavailable: 2 nodes (0-1)node 0 size: 24211 MBnode 0 free: 110 MBnode 1 size: 24240 MBnode 1 free: 150 MBnode 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/node0cpu12  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。

1) 查看有几个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 -l2

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 150 1 2 3 8 9 10 11

查看Core

/proc/cpuinfo文件中的cpu cores表明一个socket中有几个cores,例如:

cat /proc/cpuinfo | grep 'core'  | sort -ucore id: 0core id: 1core id: 10core id: 9cpu 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 -l16

其实,每个socket中能有几个processor也可以从siblings字段中获取:

$ grep 'siblings' /proc/cpuinfo | sort -usiblings: 8

信息汇总

基于以上查看CPU拓扑信息的方法,简单的写了一个小程序来查询:

#!/bin/bash# Simple print cpu topology# Author: kodangofunction 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 ====='echoecho '+--------------+---------+-----------+'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 ' '`     fidone < /proc/cpuinfoechoawk -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/cpuinfoechoecho '===== CPU Info Summary ====='echonr_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_socketecho "Cores in total: $nr_cores"if [ "$nr_cores" = "$nr_processor" ]; then    echo "Hyper-Threading: off"else    echo "Hyper-Threading: on"fiechoecho '===== 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 15Socket 1: 0 1 2 3 8 9 10 11===== CPU Info Summary =====Logical processors: 16Physical socket: 2Siblings in one socket:  8Cores in one socket:  4Cores in total: 8Hyper-Threading: on===== END =====
0 0