NUMA介绍
文章目录
什么是 NUMA?
NUMA(非统一内存访问)是一种多处理器系统的内存架构,其中内存访问时间取决于内存相对于处理器的位置。在 NUMA 系统中,处理器可以比访问远程内存更快地访问本地内存。
传统 SMP 架构的问题
在早期的对称多处理器(SMP)系统中:
- 所有 CPU 通过共享总线访问统一的内存池
- 随着 CPU 数量增加,总线成为瓶颈
- 内存带宽无法满足多个 CPU 的需求
传统 SMP 架构:
CPU1 ─┐
CPU2 ─┼─── 共享总线 ─── 内存
CPU3 ─┤
CPU4 ─┘
NUMA 的解决方案
NUMA 通过将系统划分为多个节点来解决这个问题:
- 每个节点包含一组 CPU 和本地内存
- 节点之间通过高速互连网络连接
NUMA 架构:
节点0: CPU0,CPU1 ── 本地内存0
│
├─── 互连网络 ──——─┤
│ │
节点1: CPU2,CPU3 ── 本地内存1
NUMA 的核心概念
1. NUMA 节点 (NUMA Node)
- 一个 NUMA 节点包含一组 CPU 核心和与之关联的本地内存
- 现代服务器通常有 2-8 个 NUMA 节点
2. 本地内存 vs 远程内存
- 本地内存:CPU 可以直接访问的同节点内存,访问延迟最低
- 远程内存:位于其他 NUMA 节点的内存,需要通过互连网络访问
3. NUMA 距离
系统用数值表示节点间的"距离":
# 查看 NUMA 距离矩阵
$ numactl --hardware
available: 2 nodes (0-1)
node 0 cpus: 0 1 2 3
node 0 size: 16384 MB
node 1 cpus: 4 5 6 7
node 1 size: 16384 MB
node distances:
node 0 1
0: 10 20
1: 20 10
NUMA 的性能特征
内存访问延迟对比
本地内存访问: ~100ns
远程内存访问: ~150-300ns
跨节点带宽: 本地带宽的 50-70%
NUMA 的优化策略
1. CPU 亲和性 (CPU Affinity)
将进程/线程绑定到特定的 NUMA 节点:
# 将进程绑定到节点 0
numactl --cpunodebind=0 --membind=0 ./my_program
# 将进程绑定到特定 CPU
taskset -c 0,1,2,3 ./my_program
2. 内存策略
# 本地分配策略(默认)
numactl --localalloc ./program
# 交错分配策略
numactl --interleave=all ./program
# 首选节点策略
numactl --preferred=0 ./program
3. 编程层面的优化
#include <numa.h>
void numa_aware_programming() {
// 检查 NUMA 可用性
if (numa_available() < 0) {
printf("NUMA not available\n");
return;
}
// 获取当前节点
int current_node = numa_node_of_cpu(sched_getcpu());
// 在当前节点分配内存
void *mem = numa_alloc_onnode(size, current_node);
// 设置内存策略
numa_set_localalloc();
// 绑定到当前节点
numa_run_on_node(current_node);
}
NUMA 相关工具和命令
1. 查看 NUMA 信息
# 查看 NUMA 拓扑
lscpu | grep NUMA
numactl --hardware
lstopo # 需要安装 hwloc
# 查看进程的 NUMA 使用情况
numastat
numastat -p <pid>
# 查看内存使用情况
cat /proc/meminfo
cat /proc/buddyinfo
2. 监控 NUMA 性能
# 查看 NUMA 命中率
numastat -c
# 使用 perf 监控 NUMA 事件
perf stat -e node-loads,node-load-misses ./program
3. 调试 NUMA 问题
# 查看进程的内存映射
cat /proc/<pid>/numa_maps
# 查看 NUMA 平衡统计
cat /proc/vmstat | grep numa
4. 性能调优
# 禁用自动 NUMA 平衡(可能提高性能)
echo 0 > /proc/sys/kernel/numa_balancing
# 调整 zone_reclaim_mode
echo 1 > /proc/sys/vm/zone_reclaim_mode