NUMA 架构科普:双路 CPU 系统是如何构建的?
NUMA(Non-Uniform Memory Access,非一致性内存访问)是一种用于多处理器系统的内存架构设计,主要应用于服务器、工作站和高性能计算(HPC)领域。它的核心特点是 不同 CPU 访问不同内存区域的速度不一致,这与传统的 UMA(Uniform Memory Access,一致性内存访问)架构不同。
1. NUMA 的物理结构
(1)双路 CPU 系统的硬件组成
在典型的双路(2P)服务器主板上,会有:
-
2 颗物理 CPU(如 Intel Xeon 或 AMD EPYC),分别称为 CPU0 和 CPU1。
-
每个 CPU 直接连接一部分内存(称为 本地内存)。
-
CPU 之间通过高速互联总线通信(如 Intel 的 QPI/UPI 或 AMD 的 Infinity Fabric)。
-
PCIe 设备(如 SSD、网卡)通常挂载在某一颗 CPU 的 PCIe 控制器上。
(2)内存访问方式
-
本地内存访问(Local Access)
-
CPU0 访问自己直连的内存(Node 0)速度最快(延迟低,带宽高)。
-
CPU1 访问自己直连的内存(Node 1)同理。
-
-
远程内存访问(Remote Access)
-
如果 CPU0 要访问 CPU1 的内存(Node 1),必须经过 CPU 间互联总线,这会增加延迟(通常比本地访问慢 1.5-2 倍)。
-
(3)PCIe 设备的归属
-
每个 CPU 通常控制一部分 PCIe 插槽:
-
例如,PCIe 插槽1 由 CPU0 管理,插槽2 由 CPU1 管理。
-
如果虚拟机或应用程序运行在 CPU0,但 SSD 挂在 CPU1 的 PCIe 插槽上,I/O 路径会变长,性能下降。
-
2. NUMA 的逻辑结构(操作系统视角)
在 Linux 系统中,NUMA 架构会被抽象为多个 NUMA 节点(Node):
-
每个 NUMA Node 包含:
-
一组 CPU 核心(包括物理核和超线程)。
-
一部分本地内存。
-
直接连接的 PCIe 设备。
-
查看 NUMA 拓扑
numactl -H
输出示例:
available: 2 nodes (0-1) # 2 个 NUMA 节点
node 0 cpus: 0 1 2 3 4 5 6 7 8 9 20 21 22 23 24 25 26 27 28 29
node 0 size: 65420 MB # Node 0 的内存大小
node 1 cpus: 10 11 12 13 14 15 16 17 18 19 30 31 32 33 34 35 36 37 38 39
node 1 size: 65400 MB # Node 1 的内存大小
node distances:
node 0 1 0: 10 21 # Node 0 访问本地内存的代价是 10,远程是 211: 21 10 # Node 1 同理
3. NUMA 对性能的影响
(1)内存访问性能
-
本地访问(Local Access):延迟低,带宽高(最佳性能)。
-
远程访问(Remote Access):延迟高,带宽较低(性能下降)。
(2)PCIe 设备性能
-
如果 应用程序运行在 Node 0,但 SSD/网卡挂在 Node 1,数据必须经过 CPU 间总线传输,导致延迟增加。
-
优化方法:让应用程序和 PCIe 设备尽量在同一个 NUMA Node。
(3)虚拟机性能
-
如果虚拟机(VM)的 vCPU 跨多个 NUMA Node,内存和 I/O 访问会变慢。
-
优化方法:使用
numactl
或 KVM 的<numatune>
绑定虚拟机到单一 Node。
4. 如何优化 NUMA 性能?
(1)BIOS 设置
-
启用
NUMA Support
(必须开启)。 -
禁用
Memory Interleaving
(避免内存交错,降低远程访问概率)。 -
启用
PCIe ACS
(确保 PCIe 设备能正确归属到 NUMA Node)。
(2)操作系统优化
-
绑定进程到特定 NUMA Node:
numactl --membind=0 --cpunodebind=0 ./program # 绑定到 Node 0
-
查看 PCIe 设备的 NUMA 归属:
lspci -vv | grep -i numa cat /sys/bus/pci/devices/0000:01:00.0/numa_node
(3)KVM 虚拟机优化
<domain type='kvm'><numatune><memory mode='strict' nodeset='0'/> <!-- 内存绑定到 Node 0 --></numatune><cputune><vcpupin vcpu='0' cpuset='0'/> <!-- vCPU 绑定到 Node 0 的物理核 --><vcpupin vcpu='1' cpuset='1'/><emulatorpin cpuset='0-19'/> <!-- QEMU 进程绑定到 Node 0 --></cputune>
</domain>
5. 总结
-
NUMA 架构的核心特点:不同 CPU 访问不同内存的速度不一致。
-
双路系统:两颗 CPU 各自管理部分内存和 PCIe 设备,通过高速总线互联。
-
性能关键:尽量让应用程序、内存、PCIe 设备在同一个 NUMA Node。
-
优化方法:BIOS 设置、
numactl
绑定、KVM 虚拟机 NUMA 调优。
如果你的双路系统性能不如单路,通常是因为 跨 NUMA 访问 或 PCIe 设备归属问题,按照上述方法优化即可。