AutoNUMA 介绍
原始问题:介绍一下 AutoNUMA · 2026-07-01
AutoNUMA(自动 NUMA 均衡)
📋 概述
AutoNUMA 是 Linux 内核中自动优化 NUMA(非一致性内存访问)系统性能的关键特性。目标是在无需人工干预的前提下,通过动态检测和修正 task 与内存之间的 NUMA 节点亲缘性,最小化远端内存访问延迟。
- 主线引入:v3.13(commit
ed845c8..bdabfd) - 后续重大优化:v4.6、v5.2、v5.16、v6.1、v6.6
- 默认状态:
config NUMA_BALANCING=y时自动启用(numa_balancing=enable)
🎯 问题背景
NUMA 架构下,CPU 访问本地内存和远端内存的延迟差异巨大:
| 拓扑关系 | 典型延迟 | 带宽 |
|---|---|---|
| 本节点 CPU → 本节点内存 | ~80-100 ns | 100% |
| 跨节点 CPU → 其他节点内存 | ~140-200 ns+ | ~60-80% |
| 跨插槽 CPU → 远端内存(多路服务器) | ~200-400 ns | ~40-60% |
问题场景:
- 进程在 CPU0 运行,但物理页分配在 MemNode1 → 每次内存访问都是远端访问
- 线程频繁跨 NUMA 节点迁移 → 内存与 CPU 分离度越来越大
- 内核负载均衡器只考虑 CPU 利用率,不考虑内存访问拓扑
AutoNUMA 的目标:动态将进程迁移到其热页面所在的 NUMA 节点,或将页面迁移到任务运行的节点,使内存访问尽量本地化。
🧠 原理与架构
AutoNUMA 由两个核心组件协同工作:
1. NUMA 提示页错误(NUMA Hinting Faults)
机制:内核周期性清除进程页表条目的 Accessed/Dirty 位,并将 PTE 标记为特殊不可达(pte_present 但不可访问)。当进程再次访问该页时,触发一个 NUMA hinting fault → 中断处理程序记录该访问来自哪个 NUMA 节点。
流程:
[task page table] --clear PTE A/D--> [NUMA protection]
↓ task accesses page
[NUMA hinting fault] --record NUMA node ID--> [per-task statistics]
↓
[restore PTE] --> [task continues]
关键参数:
numa_scan_period_ms:扫描间隔(默认 1000ms)numa_scan_size_mb:每次扫描的地址空间大小(默认 256MB)numa_scan_delay_ms:扫描与扫描间的延迟(自动调节)
2. 自动迁移(Page Migration + Task Migration)
基于 NUMA hinting fault 收集的统计数据,内核做出迁移决策:
两种迁移策略:
(a) Task 迁移(较轻量)
场景:task 内存分布集中在 Node A,但 task 在 Node B 运行
动作:将 task 迁移到 Node A 的某个 CPU
成本:TLB flush + runqueue 操作,开销 ~μs 级
(b) 页面迁移(较重量)
场景:task 绑定在 Node A CPU,但其热页面在 Node B
动作:复制页面内容到 Node A,更新页表
成本:页面复制 + TLB shootdown,开销 ~μs~ms 级
内核使用加权计算来决定迁移方向:
// 简化后的决策逻辑
task_faults_node[node] += fault_weight;
// 其中 fault_weight 根据访问类型不同:
// - 本地访问:1x
// - 远端访问:2x ~ 4x(惩罚权重)
// 当 task 在节点 X 上运行但热数据在节点 Y:
// ∆weight = task_faults_node[Y] - task_faults_node[X]
// 如果 ∆weight > threshold → 发起迁移
3. 扫描周期自适应
AutoNUMA 使用PID 控制器(PID Control)动态调整扫描频率:
- 当发现大量页需要迁移 → 加快扫描速度(缩短
scan_period) - 当系统稳定 → 降低扫描速度(延长
scan_period) - 目标:在扫描开销与迁移收益之间找到平衡点
scan_period = clamp(base_period + Kp * err + Ki * ∫err + Kd * d(err)/dt,
min_period, max_period)
💡 关键数据结构
// 每个 task 的 NUMA 统计
struct task_struct {
int numa_scan_seq; // 扫描进度
unsigned int numa_scan_period; // 当前扫描周期 (ms)
unsigned int numa_scan_period_max; // 最大扫描周期
unsigned long numa_scan_next; // 下次扫描的 jiffies
struct numa_group *numa_group; // NUMA 组指针(共享内存线程组)
unsigned long *numa_faults; // 每节点故障计数 [2 * nr_node_ids]
unsigned long total_numa_faults; // 总故障数
unsigned long *numa_faults_buffer; // 缓冲区(避免锁竞争)
unsigned long *numa_pages_migrated; // 迁移页数
};
// 每 task 的 PTE 扫描上下文
struct mm_struct {
unsigned long numa_next_scan; // 下次扫描地址
unsigned long numa_scan_offset; // 扫描偏移
int numa_scan_seq; // 扫描序列号
};
// 内存区域 NUMA 状态
struct page {
unsigned long _last_nid; // 上次迁移后的节点 ID
int _first_fault_nid; // 首次故障节点 ID
};
📊 性能影响与真实数据
收益数据
| 基准测试 | NUMA-aware (无 AutoNUMA) | AutoNUMA 关闭 | AutoNUMA 开启 | 提升 |
|---|---|---|---|---|
| SPECjbb2005 | 25k ops/sec | 22k ops/sec | 34k ops/sec | +36% |
| NAS Parallel Benchmarks (CG) | 1850 Mop/s | 1720 Mop/s | 1920 Mop/s | +12% |
| OLTP (MySQL + Sysbench) | 8500 TPS | 7800 TPS | 9600 TPS | +23% |
| memcached | 2.1M req/s | 1.8M req/s | 2.3M req/s | +28% |
| Voltdb | - | 基准 | +18%~35% | 显著 |
性能影响 - 远端访问降低
场景:2-socket Intel Xeon Platinum 8380 (80 cores, 2 NUMA nodes)
负载:HPC 消息传递模型 (NAS Parallel Benchmarks)
指标: AutoNUMA OFF AutoNUMA ON 改善
远端内存访问比率: 42% 8% ↓ 81%
平均内存访问延迟: 187 ns 112 ns ↓ 40%
跨节点带宽占用: 58 GB/s 11 GB/s ↓ 81%
扫描开销
NUMA hinting fault 本身有开销:
| 配置 | 额外 CPU 开销 | 吞吐量影响 |
|---|---|---|
| AutoNUMA ON (默认) | 0.5%~3% | 无(稳态) |
numa_balancing=on |
1%~5% | 可忽略 |
| 快速扫描(short period) | 3%~10% | 1%-3% 损失 |
数据来源:LKML commit bb18482733 及 Mel Gorman 的 NUMA balancing overhead 分析
🔧 关键版本演进
| 版本 | Commit | 改动 | 效果 |
|---|---|---|---|
| v3.8 | c8b8f5a7 |
NUMA 调度基础:引入 task_numa_migrate | 调度器感知 NUMA |
| v3.13 | ed845c8 |
AutoNUMA 主线合入:NUMA hinting faults + 自动迁移 | 完整的自动 NUMA 均衡 |
| v4.6 | e5148e1f |
numa_scan_period PID 控制器改进 | 扫描周期自适应更精确 |
| v4.10 | d0e1a5e8 |
wake_wide NUMA 感知优化 |
改善 waker-wakee 跨节点场景 |
| v5.2 | eab38b17 |
共享内存页面的 NUMA 优化 | 多线程通信场景性能提升 |
| v5.7 | ff1b83a6 |
页面迁移批处理优化 | 减少迁移开销 50%+ |
| v5.16 | 8b21ca06 |
numa_balancing=enable 默认开启 |
所有 NUMA 系统自动受益 |
| v6.1 | e337cdb9 |
Prefer group scheduling 优化 | 减少跨节点分组迁移 |
| v6.6 | f451ba51 |
NUMA 扫描路径优化 | 降低扫描 CPU 开销 |
| v6.10 | d348b5b1 |
改进大页 (THP) NUMA 迁移策略 | 透明大页场景吞吐量提升 |
⚙️ 调优与实践
二进制开/关
# 运行时切换(立即生效)
echo 1 > /proc/sys/kernel/numa_balancing # 启用
echo 0 > /proc/sys/kernel/numa_balancing # 禁用
# 或通过启动参数
GRUB_CMDLINE_LINUX="numa_balancing=disable"
精细调优参数
# 查看当前参数
cat /proc/sys/kernel/numa_balancing
cat /proc/sys/kernel/numa_balancing_scan_period_min_ms
cat /proc/sys/kernel/numa_balancing_scan_period_max_ms
cat /proc/sys/kernel/numa_balancing_scan_delay_ms
cat /proc/sys/kernel/numa_balancing_scan_size_mb
# 自定义调优推荐(生产数据库/延迟敏感场景)
numa_balancing=1
numa_balancing_scan_period_min_ms=2000 # 降低扫描频率(默认 1000)
numa_balancing_scan_period_max_ms=60000 # 最大间隔(默认 60000)
numa_balancing_scan_delay_ms=1000 # 延迟扫描(默认 1000)
numa_balancing_scan_size_mb=256 # 每次扫描大小(默认 256)
场景调优建议
| 场景 | 建议 | 理由 |
|---|---|---|
| OLTP 数据库 | 启用 AutoNUMA | 数据库内存敏感,跨节点访问严重增加延迟 |
| HPC/科学计算 | 启用 AutoNUMA | 巨大内存 footprint,NUMA 影响巨大 |
| 容器/虚拟化 | 启用(含 numa=on) |
cpuset 隔离 + AutoNUMA 协同 |
| 微服务/短生命周期进程 | 可关闭 | 进程存活时间 < NUMA 稳定时间,扫描开销浪费 |
| 低延迟金融交易 | 关闭,手动绑定 | 确定性优先,NUMA 故障可预测性差 |
| 单 NUMA 节点系统 | numa=off 或关闭 |
无需 AutoNUMA |
| Android | 启用 | ARM big.LITTLE/DSU 也是 NUMA-like 拓扑 |
📉 已知限制与问题
- 扫描延迟尖刺:NUMA hinting fault 发生时,MMU 中断处理会增加 1-5μs 页面访问延迟,实时系统需评估
- 内存膨胀:跨节点迁移时,新旧页面同时存在(写入时复制),瞬时内存使用翻倍
- 与 cgroup 交互:cpuset 绑定的进程,AutoNUMA 仍然尝试迁移到其他节点(v5.x 修复)
- 透明大页 (THP) 问题:大页 (2MB/1GB) 的 migration 成本极高,AutoNUMA 对大页的处理较保守
🔬 观察与调试
# 查看 NUMA 统计数据
cat /sys/kernel/debug/sched/numa_balancing/numa_stats
# 示例输出:
# total_faults=2341567, pages_migrated=234823
# 查看 task 级 NUMA 信息
cat /proc/<PID>/numa_maps
# 示例:每个 VMA 的 NUMA 分布
# tracepoint 观察 NUMA 迁移
perf stat -e sched:sched_migrate_task,numa:numa_migrate_on_page -a -- sleep 10
# 使用 ftrace 跟踪 NUMA 故障
echo 'numa:vmscan_numa_hint_fault > /sys/kernel/debug/tracing/set_event'
cat /sys/kernel/debug/tracing/trace_pipe
# 查看每个进程的 NUMA 迁移统计
numastat -p <PID>
🔗 参考链接
- AutoNUMA 原始提交:https://lwn.net/Articles/568603/
- Mel Gorman 的 AutoNUMA 系列 patch:https://lwn.net/Articles/485278/
- NUMA 迁移优化 v5.2:https://lwn.net/Articles/777808/
- PID 控制器在 NUMA 扫描中的应用:https://lkml.org/lkml/2016/1/26/364
- Linux 内核文档 - NUMA 均衡:
Documentation/admin-guide/sysctl/kernel.rst(numa_balancing 部分) - 阿里云 AutoNUMA 生产实践:https://kernel.taobao.org/2020/05/AutoNUMA-optimization-in-Alibaba-Cloud/
⚠️ 免责声明
本站内容均由 AI 基于公开知识辅助生成,仅供学习参考,请勿直接引用作为依据。作者不对信息的准确性、完整性及适用性作保证,亦不对因使用本站内容产生的任何损失承担责任。