暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

关于 NUMA 绑核,你需要了解的。。。

原创 OnTheRoad 2022-09-13
6815

1. NUMA 的前世今生

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

下图为 UMA 架构图

image.png

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

image.png

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 内的内存块,那这样的效率就是最高的。

image.png

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
复制
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论

目录
  • 1. NUMA 的前世今生
    • 1.1 NUMA 中的概念
  • 2. Linux 中的 NUMA
    • 2.1 numactl 安装
    • 2.2 查看 CPU 架构
    • 2.3 Linux 中的绑核策略
    • 2.4 查看 NUMA 运行信息
    • 2.5 NUMA 绑核示例
    • 2.6 禁用 NUMA