NUMA(non-uniform memory access)是一种用于多处理器系统的内存设计,其中内存访问的时间取决于内存与处理器的距离。 本文将会记录与 NUMA 相关的常用命令。

环境

$ distro
Name: openEuler 22.03 (LTS-SP4)
Version: 22.03 (LTS-SP4)
Codename: LTS-SP4

查询可用节点信息

numactl -H
  • 各节点对应的 CPU 核心编号
  • 各节点内存的粗略使用情况
  • 节点之间的距离
lscpu

lscpu 可用于查询 CPU 架构信息,包括:

  • 插槽(socket):主板上的 CPU 插槽,也就是俗称的“路”。
  • 核心(core):可以查询到每路 CPU 的核心数。
  • 线程(thread):每个核心具有的硬件线程数,可能大于一,比如常见的超线程。
  • NUMA 节点以及对应的核心编号。

查询当前进程的 NUMA 策略配置

numactl -s

NUMA 策略是配置在命令上的,且能够被其子进程继承。 NUMA 策略包括:

  • 绑定的 NUMA 节点
  • 绑定的 CPU 核心
  • 偏好的 NUMA 节点,内存会被优先分配到该节点上

查询各 NUMA 节点内存分配命中情况

numastat

不带任何参数的 numastat 命令能够查询各 NUMA 节点内存命中与否的统计信息,这些信息来自内核分配器。 会对每个节点输出以下各个类型的内存页数量:

  • numa_hit:内存成功分配到预期的节点上。
  • numa_miss:进程偏好分配到其他节点上,但实际分配到了该节点上,与 numa_foreign 成对出现。
  • numa_foreign:内存预期分配到该节点,但实际分配到了其他节点上,与 numa_miss 承兑出现。
  • interleave_hit:预期交错分配的内存成功分配到该节点上。
  • local_node:进程与其分配的内存都在该节点上。
  • other_node:分配内存的进程运行在其他节点上。

其中预期分配的节点一般是进程的本地节点或者是由 --preferred 参数指定的节点。

numastat -c

带上 -c 参数后输出信息会更加紧凑,并且内存页数量会被换算为兆字节(MB)。

watch -n1 --differences=cumulative numastat

numastat 命令输出的是累积的统计信息,如果想查询一段时间内的分配情况,可以配合 watch 命令使用。

查询各节点内存使用情况

numastat -m

各节点的输出信息与 /proc/meminfo 类似。

配置节点内内存回收策略

vm.zone_reclaim_mode 用于指定单个 NUMA 节点内存不足时在节点内回收(reclaim)内存的策略。 它的默认值为 0,表示不先进行回收,而是优先从其他 NUMA 节点尝试分配内存。 激进的内存回收策略通常情况下会导致性能问题,所以应当保持默认值。

sysctl -n vm.zone_reclaim_mode
sysctl -w vm.zone_reclaim_mode=0

配置自动 NUMA 内存平衡

numa_balancing 用于开启或关闭基于缺页的自动 NUMA 内存平衡。 该内核参数开启时,内核会将内存移动到访问更频繁的 NUMA 节点,这能够减少跨 NUMA 的内存访问。 系统内核会周期性地清除页表映射,在缺页中断时对各个线程访存情况进行采样,同时依据采样结果将被访问的数据迁移到合适的 NUMA 节点上。 这些缺页中断会带来额外的开销。

理想情况下,相比缺页的损耗,该特性减少的远端访存能够带来更高的收益。 但是 openGauss 本身的内存分配是 NUMA-aware 的,不需要依赖自动平衡,所以这种情况下就应该关闭该特性(配置为 0)。

sysctl -n kernel.numa_balancing
sysctl -w kernel.numa_balancing=0

查询 PCIe 设备对应的 NUMA 节点

/sys/class 目录依据类别(网卡、硬盘等)存放系统中注册的各个设备,其子目录中存放的是各设备的软链接,指向 /sys/devices 中的对应目录。 如下命令会遍历该目录中的设备并输出其 NUMA 节点信息(如果有):

for file in /sys/class/*/*/device/numa_node; do
  echo ${file}
  cat ${file}
done

这里再提供一个示例。 查询指定目录挂载 NVMe 硬盘对应的 NUMA 节点:

# 查询挂载信息
df -h

# 查询 NUMA 节点信息
cat /sys/class/nvme/nvme0/numa_node