【linux numa】 NUMA 绑核

1. NUMA 的前世今生

NUMANon Uniform Memory Access)和 UMAUniform Memory Access)是两种 CPU 相关的硬件架构。在早期的 UMA 架构中,CPU 通过前端总线(FSB,Front Side Bus)连接到北桥芯片,然后北桥芯片连接到内存,即内存控制器集成在北桥芯片中。外部 IO 设备与南桥芯片相连,南桥芯片与北桥芯片通过内部总线相连。

下图为 UMA 架构图

【linux numa】 NUMA 绑核_第1张图片

下图为早期的 UMA 架构主板。图中,靠近 CPU 黄色框线处为北桥芯片,其内部集成了内存控制器,通过 FSB 前端总线与 CPU 互联。靠近 BIOS 电池红色框线处为南桥芯片,集成了外围 IO 设备的控制器(如USB、Audio等),通过内部总线与北桥芯片互联。

100%•75%•50%

总线模型保证了 CPU 的所有内存访问都是一致的,不必考虑不同内存地址之间的差异。优点是资源共享,而缺点是总线争用激烈。随着服务器中 CPU 数量的增多,FSB 总线争用的弊端慢慢越来越明显,成为了系统瓶颈。于是,为了消除 FSB 的瓶颈,Intel 在 Nehalem CPU 上推出了 NUMA 架构。AMD 在引入 64 位 x86 架构时,也实现了 NUMA 架构。

1.1 NUMA 中的概念

  • CPU 厂商将内存控制器芯片集成到 CPU 内部,一般一个 CPU socket 会有一个独立的内存控制器
  • 每个 CPU scoket 独立直连到一部分内存,这部分直连内存称为此 CPU 的 “本地内存”。
  • 每个 CPU socket 与其直连的 “本地内存”,可称为一个 “Numa Node”。
  • 多个 CPU 之间通过 QPI(Quick Path Interconnect)总线进行连接。CPU 可以通过 QPI 总线访问不与自己直连的 “远程内存”。
  • Numa Node 内的 CPU 读写其内部的 “本地内存” 延迟最低,效率最高;通过 QPI 总线读写其他 Numa Node 中的内存(称为 “远程内存”),则延迟增加,效率降低。

如下图所示,一台服务器包含 2 个处理器、4 个内存块。NUMA 架构将 1 个处理器与 2 个内存块合起来(如将 Processor1 与 Memory1.1Memory1.2 结合)称为一个 “NUMA Node”。如此,这台服务器共有 2 个 NUMA Node。在物理分布上,NUMA Node 内的处理器和内存块的物理距离更小,因此访问速度也更快。如下图所示,NUMA Node1 的 Processor1 访问 Memory1.1 和 Memory1.2 比访问Memory2.1 和 Memory2.2 更快。所以,使用 NUMA 的模式,如果能尽量保证本 Node 内的 CPU 只访问本 Node 内的内存块,那这样的效率就是最高的。

【linux numa】 NUMA 绑核_第2张图片

100%•75%•50%

2. Linux 中的 NUMA

2.1 numactl 安装

Linux 提供了一个 NUMA 绑核工具 numactl(默认不安装),在 CentOS 中安装命令如下:

sudo yum install numactl −y

2.2 查看 CPU 架构

通过 “lscpu” 命令,可查看系统中的处理器是否为 NUMA 架构。

~]$ sudo lscpu
Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                64
On-line CPU(s) list:   0-63
Thread(s) per core:    2
Core(s) per socket:    16
Socket(s):             2
NUMA node(s):          2
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 85
Model name:            Intel(R) Xeon(R) Silver 4216 CPU @ 2.10GHz
Stepping:              7
CPU MHz:               2699.981
CPU max MHz:           3200.0000
CPU min MHz:           800.0000
BogoMIPS:              4200.00
Virtualization:        VT-x
L1d cache:             32K
L1i cache:             32K
L2 cache:              1024K
L3 cache:              22528K
NUMA node0 CPU(s):     0-15,32-47
NUMA node1 CPU(s):     16-31,48-63

结果显示,系统中包含 2 个 Numa Node。其中,"0-15,32-47" 核属于 Numa Node1、"16-31,48-63" 属于 Numa Node2。通过如下的 “numactl --hardware’’ 也可以验证这一信息。除此之外,”numactl --hardware’'还展示了每个 Numa Node 的本地内存分配,以及访问本地内存、远程内存的距离(distance)信息。

~]$ sudo numactl --hardware
available: 2 nodes (0-1)
node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
node 0 size: 31692 MB
node 0 free: 29048 MB
node 1 cpus: 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
node 1 size: 32234 MB
node 1 free: 30114 MB
node distances:
node   0   1 
    0:  10  21 
    1:  21  10 

2.3 Linux 中的绑核策略

~]$ sudo numactl --show
policy: default
preferred node: current
physcpubind: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 
cpubind: 0 1 
nodebind: 0 1 
membind: 0 1 

示例中显示,当前绑核策略为 "default’’。"default’’ 默认策略为 "--localalloc’’。内存绑核策略包括:

  • --localalloc 或者 -l:进程尝试从本地节点上请求分配内存,如果失败则从其他 Node 上申请内存。
  • --membind=nodes 或者 -m nodes:规定进程只能从指定的 nodes 上请求分配内存。当在 TiDB 集群的配置文件中为 TiDB/PD/TiKV 指定 numa_node 参数时,即相当于以 membind策略为 TiDB 组件进行 Numa 绑核。
tidb_servers:
- host: 192.168.3.221
  ssh_port: 22
  port: 4000
  status_port: 10080
  deploy_dir: /tidb-deploy/tidb-4000
  log_dir: /tidb-deploy/tidb-4000/log
  numa_node: "0,1"
  arch: amd64
  os: linux
  • --preferred=node:优先从指定 node 请求内存分配,如果获取失败,则尝试其他 node。
  • --interleave=nodes 或者 -i nodes:规定进程从指定的 nodes 上,以 round robin 算法轮询地请求内存分配。

2.4 查看 NUMA 运行信息

可通过 ·numastat· 查看系统中 ·numa node· 的运行信息。

~]$ numastat
                           node0           node1
numa_hit              2428976598      1126105874
numa_miss                1226502       259640186
numa_foreign           259640186         1226502
interleave_hit             23412           23575
local_node            2428960674      1126067489
other_node               1242426       259678571
  • numa_hit命中的内存,也就是为这个节点成功分配本地内存访问的内存大小。
  • numa_miss将内存访问分配到另一个 node 节点的内存大小,这个值和另一个 node 的 numa_foreign 相对应。如 node0 的 numa\_miss 与 numa\_node1 的 numa_foreign 相对应。
  • numa_foreign另一个 Node 访问此 Node 的内存大小,与对方 Node 的 numa_miss 相对应。如 node0 的 numa_foreign 与 numa_node1 的 numa_miss 相对应。
  • local_node这个节点的进程,成功在这个节点上分配内存访问的大小。
  • other_node这个节点的进程,在其它节点上分配的内存访问大小。

很明显,miss 值和 foreign 值越高,就需要考虑 numa 绑定的问题。但是,如果本身内存资源就不足,则可直接禁用 NUMA 特性。

2.5 NUMA 绑核示例

## 将 myapplic 运行在 cpus 0-4、8-12 中
numactl --physcpubind=+0-4,8-12 myapplic arguments 

## 将 bigdatabase 运行在所有 cpu node 中,参数为 argments
numactl --interleave=all bigdatabase arguments 

## 将 process 运行在 node0,并从 node0、node1 申请内存
numactl --cpunodebind=0 --membind=0,1 process

## 将 process 运行在 node0,并从 node0、node1 申请内存 balancing
numactl --cpunodebind=0 --balancing --membind=0,1 process

## 将 network-server 运行在 eth0 所属的 node 中,并从该 node 中申请内存
numactl --cpunodebind=netdev:eth0 --membind=netdev:eth0 network-server 

## 以 node0 为首选,执行 numactl --show
numactl --preferred=0 numactl --show 

2.6 禁用 NUMA

针对 Oracle、MySQL 数据库,开启 Numa 可能会带来性能问题,因此建议关闭 Numa 特性。可通过如下方式,关闭 Numa:

  1. 通过 BIOS 关闭通过主板 BIOS 禁用 NUMA 特性,不同的主板路径可能不同。
BIOS:interleave = Disable / Enable
  1. 通过操作系统关闭

Linux 操作系统,可编辑 /etc/default/grub 文件,在参数 GRUB_CMDLINE_LINUX 的值的末尾,追加上 numa=off。以 CentOS7 为例。

## 修改 grub 文件
~]# 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="crashkernel=auto rd.lvm.lv=ol/root rd.lvm.lv=ol/swap rhgb quiet numa=off"
GRUB_DISABLE_RECOVERY="true"

## 重新生成启动配置
~]# cp /boot/grub2/grub.cfg /boot/grub2/grub.cfg.bak
~]# cp /boot/efi/EFI/redhat/grub.cfg /boot/efi/EFI/redhat/grub.cfg.bak
~]# grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-3.10.0-1127.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-1127.el7.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-0ffe1c969db740f3bf50f4567ee5fba5
Found initrd image: /boot/initramfs-0-rescue-0ffe1c969db740f3bf50f4567ee5fba5.img
done

~]# grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-3.10.0-1127.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-1127.el7.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-2b736cc499234bc4953ba55d0dd9288c
Found initrd image: /boot/initramfs-0-rescue-2b736cc499234bc4953ba55d0dd9288c.img

## 重启系统,确认生效
~]# dmesg | grep -i numa
[    0.000000] Command line: BOOT_IMAGE=/vmlinuz-3.10.0-327.el7.x86_64 root=/dev/mapper/centos-root ro crashkernel=auto numa=off rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet[    0.000000] NUMA turned off[    0.000000] Kernel command line: BOOT_IMAGE=/vmlinuz-3.10.0-327.el7.x86_64 root=/dev/mapper/centos-root ro crashkernel=auto numa=off rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet

linux服务器linux系统numa

转载于 关于 NUMA 绑核,你需要了解的。。。 - 墨天轮

你可能感兴趣的:(linux,linux)