讲解CPU之NUMA硬件体系以及机制(lscpu查看相关信息)
先看看从系统层面反映出来的numa cpu信息。
采样机器为实体机、80核、128内存。
[root@ht2 src]# lscpu
Architecture: x86_64 #x86架构下的64位
CPU op-mode(s): 32-bit, 64-bit #表示支持运行模式,getconf LONG_BIT 命令可以得到当前CPU运行在什么模式下,如果是64,但不代表CPU不支持32bi
Byte Order: Little Endian #Intel的机器(X86平台)一般都采用小端,Little Endian代表小段字节对齐
CPU(s): 80 #逻辑cpu颗数
On-line CPU(s) list: 0-79 #正在运行的cpu逻辑内核
Thread(s) per core: 2 #每个核的线程数(每个 Core 的硬件线程数)
Core(s) per socket: 10 #多少核
Socket(s): 4 #服务器面板上有4个cpu槽位
NUMA node(s): 4 #numa nodes的数量
Vendor ID: GenuineIntel #cpu厂商ID
CPU family: 6 #CPU产品系列代号
Model: 62 #CPU属于其系列中的哪一代的代号
Model name: Intel(R) Xeon(R) CPU #cpu型号
E7-4830 v2 @ 2.20GHz //型号 Stepping: 7 #步长 CPU MHz: 2180.664 #CPU的时钟频率(主频),是指CPU运算时的工作的频率,决定计算技术的运行速度,单位是Hz CPU max MHz: 2700.0000 #cpu时钟最大频率 CPU min MHz: 1200.0000 #cpu时钟最小频率 BogoMIPS: 4389.73 #BogoMips 是衡量 CPU 速度的方法,它衡量的是“ CPU 每秒钟什么都不能做的百万次数” Virtualization: VT-x #cpu支持的虚拟化技术,需要进入进入bios设置
//要结合着理解L1d cache和L1i cache,他们两个差一个字母d和i L1d cache: 32K #ld cache 内容缓存 L1i cache: 32K #li cache 指令缓存,L1是最靠近CPU核心的缓存。
L2 cache: 256K #CPU未命中L1的情况下继续在L2寻求命中,L2二级缓存比L1一级缓存的容量要更大,但是L2的速率要更慢,离cpu远
L3 cache: 20480K #
#这里看到,cpu是采用numa硬件体系架构,首先确认看到cpu硬件是否支持numa的.
#通过lscpu 、numactl --hardware、grep -i numa /var/log/dmesg等命令可以看到相关配置。
#缓存速度上 L1 > L2 > L3 > DDR
NUMA node0 CPU(s): 0-9,40-49 #0-9和40-49 是由numa node0 来管理的
NUMA node1 CPU(s): 10-19,50-59 #...
NUMA node2 CPU(s): 20-29,60-69 #...
NUMA node3 CPU(s): 30-39,70-79 #...
Flags: fpu ..... #cpu支持的技术特征 这里省略了.另外章节介绍
注意: 如果是 1个Sockets, 4个Cores,2 Thread(s) per core 1个cpu,4核8线程
由上面上面NUMA 引出了,numa架构问题。
#一个没有启用numa的服务器。
[root@ht20 redis]# lscpu NUMA node(s): 1 NUMA node0 CPU(s): 0-15
一、先看下X86主板布局图
从图中可以看出,靠近CPU的是北桥芯片(North Bridge)
1、北桥芯片中集成了内存控制器、PCI控制器等, 主要负责和高速设备通信,如内存、显卡等。
2、北桥芯片附近的是南桥芯片(South Bridge),主要负责和一些低速外设之间的通信。
另外,内存插槽和PCI插槽都是靠近北桥芯片的,目的就是减少这些插槽到北桥芯片之间的布线长度,
从而降低北桥芯片和这些设备的通信延迟和干扰。
二、芯片组系统框架(北桥)
如图上图所示,intel 82915P是一款典型的北桥芯片,intel ICH6x是南桥芯片,这两款芯片加在一起被称为i915P芯片组。 某个芯片组的名称其实就是以北桥芯片的型号来命名的。 从上图可以了解到以下信息: 1、CPU和北桥之间通过前端总线FSB通信 2、北桥负责和显卡、内存设备通信 3、南桥负责和低速外设通信,如USB设备、硬盘等 4、南桥不能直接和CPU通信,必须经过 DMI 和北桥通信,然后统一由北桥和CPU通信
另外 Intel南桥芯片叫ICH与北桥芯片(MCH)是构成主板最重要的一个部分。MCH是内存控制器中心的英文缩写,负责连接CPU,AGP总线和内存
这个架构当然是比较的落后了,但是还是很能说明问题,毕竟芯片以及主板技术发展迅猛。
现在北桥的大部分功能已经被整合进cpu处理器中,如内存控制器和PCIe控制器。
在intel某些型号的处理器中,南桥也被整合进处理器中,从而主板上只剩下处理器一颗芯片,更类似于ARM处理器系统中的架构。
三、SMP cpu架构体系
SMP (Symmetric Multiprocessing),对称多处理器。
在SMP中所有的处理器都是对等的,所有CPU Core都是通过共享一个北桥(pci bus)来读取内存,
这也就导致了系统中所有资源(CPU、内存、I/O等)都是共享的,当我们打开服务器的背板盖,如果发现有多个cpu的槽位,
但是却连接到同一个内存插槽的位置,那一般就是smp架构的服务器。常见的pc啊,笔记本啊,手机还有一些老的服务器都是这个架构
ls /sys/devices/system/node/# 如果只看到一个node0 那就是smp架构
[root@ht4 ~]# ls /sys/devices/system/node/
has_cpu has_memory has_normal_memory node0 node1 online possible power uevent //numa架构
[root@ht20 redis]# ls /sys/devices/system/node/
has_cpu has_memory has_normal_memory node0 online possible power uevent //smp架构
smp基本工作如下图所示:
四、NUMA cpu架构体系
在NUMA硬件架构出现之前,内存控制器还是被设计在主板的北桥芯片组中,
所有CPU对内存的访问都要通过北桥芯片组来完成。
此时所有CPU访问内存都是“一致的”,在传统的对称多处理器SMP体系架构中,
整个计算机中的所有cpu共享一个单独的内存控制器。
当所有的cpu同时访问内存时,这个内存控制器往往会成为系统的性能瓶颈。
同时,smp架构也不能适应使用大量的cpu的场景。于是,为了解决这些问题,
越来越多的现代计算机系统开始采用了CC/NUMA(缓存一致性/非对称访存)架构。
例如AMD* Opteron*, IBM* Power5*, HP* Superdome, and SGI* Altix*等。
注意: 如果linux 内核不支持的话numa的话也白搭,你如果看linux 内核代码会发现很多内核会涉及到numa,同时在head.S中也有它的影子。 NUMA和SMP是两种不同的CPU硬件体系架构,可以形象的认为numa是多对多(一个node-->多个cpu core-->内存), 而SMP是 内存控制器--->多个cpu core。 NUMA 绑核是用来隔离 CPU 资源的一种方法,适合高配置物理机环境部署多实例使用,主要为了防止 CPU 资源的争抢,引发性能衰退
1、IMC 的全称是Integrated Memory Controller,集成内存控制器。IMC是内存通道控制模组。
2、QPI ,又名CSI,Common System Interface公共系统接口,是一种可以实现芯片间直接互联的架构。
3、Intel的QuickPath Interconnect技术缩写为QPI,译为快速通道互联。官方名字叫做CSI。
4、NUMA 全称 Non-Uniform Memory Access,翻译为“非一致性内存访问”。
numa 构架下,每个node都有自己独立的内存控制器和CPU core,
我们看一个开启了numa架构的服务器.
[root@ht4 ~]# numactl --hardware available: 2 nodes (0-1) #如果是2或多个nodes就说明numa没关掉 node 0 cpus: 0 1 2 3 4 5 6 7 16 17 18 19 20 21 22 23 node 0 size: 16355 MB node 0 free: 12392 MB node 1 cpus: 8 9 10 11 12 13 14 15 24 25 26 27 28 29 30 31 node 1 size: 16384 MB node 1 free: 7290 MB node distances: node 0 1 0: 10 20 1: 20 10
也就是说每个 Node 都有自己的集成内存控制器(imc)
系统板的北桥最重要的功能是内存控制器。cpu里集成内存控制器的,因为这样可以减少我们【cpu<--->内存】之间的延迟,以往的内存控制器是集成在北桥里的。
而现在的Intel CPU已经将内存控制器集成到了内部。在 Node内部,架构类似SMP架构,使用 IMC Bus 进行不同核心内部间的通信;
不同的 Node 间通过QPI进行通信
intel numa cpu模型就比较清楚的解释了运行机制
+-----------------------Node0/smp架构---------------+ +-----------------------Node1/smp架构----------------+
| +++++++++++++++ +++++++++++++++ +++++++++++++++ | | +++++++++++++++ +++++++++++++++ +++++++++++++++ |
| | CPU0 | | CPU2 | | CPU3 | | | CPU6 | | CPU7 | | CPU8 | |
| +++++++++++++++ +++++++++++++++ +++++++++++++++ | | +++++++++++++++ +++++++++++++++ +++++++++++++++ |
| | | | | | | | | |
| | | | | | | | | |
| -------------------IMC BUS-------------------- | | -------------------IMC BUS-------------------- |
| | | | | | | |
| | | | | | | |
| +++++++++++++++ +++++++++++++++ | | +++++++++++++++ +++++++++++++++ |
| | memory | | memory | | | | memory | | memory | |
| +++++++++++++++ +++++++++++++++ | + +++++++++++++++++ +++++++++++++++ |
+___________________________________________________+ +___________________________________________________+
| |
| |
| |
----------------------------------------------------QPI---------------------------------------------------
一般来说,一个内存插槽对应一个 Node。
需要注意的一个特点是,QPI的延迟要高于内存IMC Bus,也就是说CPU访问内存有了远近(remote/local)之别后,这个差别非常明显。
在Linux中,对于NUMA有以下几个需要注意的地方:
默认情况下,内核不会将内存页面从一个 NUMA Node 迁移到另外一个 NUMA Node;
但是有现成的工具可以实现将冷页面迁移到远程(Remote)的节点:NUMA Balancing;
关于不同 NUMA Node 上内存页面迁移的规则,社区中有依然有不少争论。
下面我们看下内核分析 numa node
E:\linux内核\linux-2.6.0\linux-2.6.0\arch\x86_64\kernel\head64.c //内核启动代码时候
#ifdef CONFIG_DISCONTIGMEM
s = strstr(saved_command_line, "numa=");
//启动参数存入后command_line后,会在setup_command_line中,再次将启动参数拷贝到static_command_line中
if (s != NULL)
numa_setup(s+5);
#endif
E:\linux内核\linux-2.6.0\linux-2.6.0\arch\x86_64\mm\numa.c //初始化的时候
{
.....
void __init paging_init(void)
{
int i;
for_all_nodes(i) {
setup_node_zones(i);
}
}
/* [numa=off] */
__init int numa_setup(char *opt)
{
if (!strncmp(opt,"off",3))
numa_off = 1; //默认关闭
return 1;
}......
}
在centos下查看和关闭numa,看查看文档
https://access.redhat.com/solutions/23216
E:\linux内核\linux-2.6.0\linux-2.6.0\Documentation\x86_64\boot-options.txt
//内核文档有阐述,系统关闭默认将仅仅安装为单节点。(124行)
//查看linux内核启动行,这个是grub会读取的 [root@ht2 cpu0]# cat /proc/cmdline BOOT_IMAGE=/vmlinuz-3.10.0-693.el7.x86_64 root=/dev/mapper/centos-root ro rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet LANG=en_US.UTF-8 [root@ht2 cpu0]# cat /etc/default/grub GRUB_TIMEOUT=5 GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)" GRUB_DEFAULT=saved GRUB_DISABLE_SUBMENU=true GRUB_TERMINAL_OUTPUT="console" GRUB_CMDLINE_LINUX="rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet" GRUB_DISABLE_RECOVERY="true" //安装后的系统里面修改启用numa。 [root@ht2 cpu0]# vi /etc/default/grub ## replace numa=off to numa=on [root@ht2 cpu0]#grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg [root@ht2 cpu0]#shutdown -r now
安装numa的工具,查看numa和管理numa,工具使用我用了另外一台机器,因为ht2机房太慢了
这个工具有点类似 taskset 可以对cpu的行为造成影响。
[root@fp-web-112 ~]# yum -y install numactl //centos7下很容易安装,网速足够快的情况下,安装很简单。 [root@fp-web-112 ~]# numactl -h 语法: numactl [--interleave nodes] [--preferred node] [--membind nodes] [--cpunodebind nodes] [--physcpubind cpus] [--localalloc] [--] {arguments ...} numactl --show numactl --hardware numactl [--huge] [--offset offset] [--shmmode shmmode] [--length length] [--strict] [--shmid id] --shm shmkeyfile | --file tmpfsfile [--touch] [--dump] [--dump-nodes] memory policy 主要参数: --interleave=nodes, -i nodes 这个选项用于设定内存的交织分配模式。 也就是说系统在为多个节点分配内存空间的时候,将会以轮询分发的方式被分配给这多个节点. 如果在当前众多的交织分配内存节点中的目标节点无法正确的分配内存空间的话,内存空间将会由其他的节点来分配。 --membind=nodes, -m nodes 选项 '--membind' 仅用来从节点中分配内存空间所用。 如果在这些节点中无法分配出所请求的空间大小的话该分配操作将会失败. 上述命令中指定需要分配空间的 nodes 的方式可以遵照上述 N,N,N , N-N ,N 这种方式来指定. --cpunodebind=nodes, -N nodes 上述命令仅用于施加在运行与 cpu 上的进程。这个命令用于显示 cpu 的个数,
cpu 数目信息同样记录在系统中的存放处理器领域信息的 /proc/cpuinfo 文件夹下,
或者是按照关联的中央处理器信息 在当前的中央处理器集中所存放. --localalloc , -l 这个命令选项通常是为当前的节点分配内存的 --preferred=node 该命令由于指定优先分配内存空间的节点,如果无法将空间分配给该节点的话,应该分配给该节点上的空间将会被分发到其他的节点上 该命令选项后面仅接收一个单独的节点标号. 相关的表示方式也可以使用. --show,-s 该命令用于显示 NUMA 机制作用在当前运行的那些进程上 --hardware , -H 该命令用于显示当前系统中有多少个可用的节点. --huge 当创建一个基于大内存页面的系统级的共享内存段的时候,使用 --huge 这个选项。 --huge 选项仅在 --shmid 或是 --shm 命令的后面使用才有效. --offset 该参数选项用于指定共享内存段中的位移量的偏移。 默认的情况下偏移量是 0 。 有效的偏移量单位是 m (用于表示 MB) g (用于表示 GB) , k (用于表示 KB ), 其他没有指定的被认为是以字节为单位. --strict 这个参数选项 当施加了 NUMA 调度机制的共享内存段区域的页面被施加了另一个机制而导致错误的时候, 使用 --strict 选项将会把错误信息显示出来. 默认情况是不使用该选项的。 --shmmode shmmode 该选项仅在 --shmid 或是 --shm 之前使用才会生效。 当创建一个共享内存段的时候,通过整型数值来指定 共享内存的共享的模式类型. --length length Apply policy to length range in the shared memory segment or make the segment length long Default is to use the remaining length Required when a shared memory segment is created and specifies the length of the new segment then . Valid units are m ( for MB ) , g( for GB) , k ( for KB) , otherwise it specifies bytes. --shmid id 通过ID 号码来创建或使用一个共享内存段。 (如果共享内存段已经存在,那么通过 shmid 来指定下面要使用某个 ID 的共享内存段 ; 如果该 ID 对应的共享内存段并不存在的话,那么就创建一个) --shm shmkeyfile 通过存放在 shmkeyfile(共享内存-键文件)中的 ID 号码来创建或者是使用一个共享内存段。 访问 shmkeyfile 文件的进程是通过 fork(3 arguments) 方法来实现的. --file tmpfsfile 将 numa 机制施加于文件上面, 这个文件属于 tmpfs或者是 hugetlbfs 这种特殊的文件系统 --touch 通过将 numa 机制施加于刚刚页面上来实现内存的早期 numa 化。 默认情况下是不使用该选项,如果存在映射或是访问页面的应用的话,将会使用该早期实行 NUMA 机制的这种方法. --dump 该选项用于废除将已经 numa 化的特定区域上的 NUMA性质. (--dump ) 选项后,有效指定 node 的书写方式 all 用于将所有的节点上的 NUMA 特性移除 number 通过指定 node 后接的数值来废除该数字对应的 node number1(number2) node number1(node number2)上的 NUMA 特性将会被移除 number1-number2 node number1 -- node number2 区间上的所有存在的 node 的 NUMA 特性将会被移除 !nodes 除了 nodes 所指定的节点以外的所有节点上的 NUMA 特性全都会被移除
//我们查看,linux内核文档写的很清楚,默认是关闭的,关闭的情况下仅仅是安装为单个节点。 //原文: numa=off Only set up a single NUMA node spanning all memory. [root@fp-web-112 ~]# numactl --hardware available: 1 nodes (0) //1个节点有效 node 0 cpus: 0 1 2 3 4 5 6 7 //8核都安装在这个节点下 node 0 size: 16383 MB //将近16G内存都由该节点控制 node 0 free: 3710 MB //3.6g是空闲 node distances: node 0 0: 10 //查看numa状态 [root@fp-web-112 ~]# numastat node0 numa_hit 5740940530 numa_miss 0 numa_foreign 0 interleave_hit 21170 local_node 5740940530 other_node 0
https://www.percona.com/doc/percona-server/5.5/performance/innodb_numa_support.html
https://dom.as/2014/01/17/on-swapping-and-kernels/
https://engineering.linkedin.com/performance/optimizing-linux-memory-management-low-latency-high-throughput-databases
https://engineering.linkedin.com/performance/optimizing-linux-memory-management-low-latency-high-throughput-databases