土法炼钢兴趣小组的算法知识备份

【操作系统百科】NUMA 内存

文章导航

分类入口
os
标签入口
#numa#mempolicy#autonuma#cxl#numactl

目录

NUMA(Non-Uniform Memory Access):CPU 访问本地内存 ~80ns,跨 socket 访问远端内存 ~140-200ns。多路服务器上忽略 NUMA 可能丢 30% 性能。

一、先看图

flowchart LR
    C0[CPU 0-15<br/>Node 0] --> M0[DRAM Node 0<br/>256GB, ~80ns]
    C1[CPU 16-31<br/>Node 1] --> M1[DRAM Node 1<br/>256GB, ~80ns]
    C0 -.跨 QPI/UPI.-> M1
    C1 -.跨 QPI/UPI.-> M0
    CXL[CXL 设备] -.CXL.mem.-> M2[CXL 内存<br/>Node 2, ~200ns]
    classDef local fill:#3fb95022,stroke:#3fb950,color:#adbac7;
    classDef remote fill:#f0883e22,stroke:#f0883e,color:#adbac7;
    classDef cxl fill:#a371f722,stroke:#a371f7,color:#adbac7;
    class C0,C1,M0,M1 local
    class CXL,M2 cxl

二、拓扑发现

numactl --hardware
# available: 2 nodes (0-1)
# node 0 cpus: 0 1 2 ... 15
# node 0 size: 262144 MB
# node distances:
# node   0   1
#   0:  10  21
#   1:  21  10

lscpu | grep NUMA

node distance 矩阵:10=本地,21=一跳,31=两跳(更大机器)。

三、mempolicy

Linux 给每个进程/VMA 一个内存分配策略:

# 绑定 node 0
numactl --membind=0 ./app

# 交错分配
numactl --interleave=all ./app

代码级

#include <numaif.h>
set_mempolicy(MPOL_BIND, nodemask, maxnode);

// per-VMA
mbind(addr, len, MPOL_BIND, nodemask, maxnode, MPOL_MF_MOVE);

四、AutoNUMA / NUMA balancing

4.1 问题

手动 numactl 太粗——进程运行中可能被调度器迁移到远端 CPU,或 fork 后子进程在远端 node 跑着用本地内存。

4.2 AutoNUMA 方案

内核定期把 PTE 标为不可访问(PROT_NONE)→ 触发 NUMA hint fault → 记录”谁在哪个 node 访问”→ 如果页和任务不同 node → migrate page 或 migrate task。

cat /proc/sys/kernel/numa_balancing      # 1=开启(默认)
cat /proc/vmstat | grep numa
# numa_hit    numa_miss    numa_foreign
# numa_pages_migrated

4.3 代价

NUMA hint fault 本身有开销(额外 page fault)。对 I/O 密集不明显,对计算密集可达 1-3% CPU。

关闭:

sysctl kernel.numa_balancing=0

五、page migration

内核能在 node 间迁移物理页:

migrate_pages(pid, old_nodes, new_nodes);  // syscall

numactl --hardware + migratepages 工具。

内部: 1. 在目标 node 分配新页 2. 复制内容 3. 更新所有 PTE(rmap walk) 4. 释放老页

开销:每页几 μs(含 TLB 刷新)。大批量迁移可达 ms。

六、NUMA 与调度

C-24 讲了调度器的 NUMA 感知。总结交叉:

七、CXL 与分级 NUMA

CXL(Compute Express Link)能把远端 DRAM 或持久内存挂成新的 NUMA node:

Node 0: 本地 DDR5 (~80ns)
Node 1: 远端 socket DDR5 (~140ns)
Node 2: CXL DRAM (~200-300ns)

Linux 6.x+ 支持 CXL memory hotplug、auto-node 创建。

memory tiering

2 级以上的 NUMA 层次需要分层策略:

cat /sys/devices/system/memtier/   # 查看 tier 结构

八、生产调优

8.1 数据库

# MySQL / PostgreSQL
numactl --interleave=all mysqld      # buffer pool 均匀分布
# 或 membind 配合 CPU 绑定

为什么 interleave?DB buffer pool 几十 GB,所有 CPU 都访问,interleave 避免单 node 热点。

8.2 JVM

numactl --localalloc java -Xmx32g ...
# JVM 大堆用 -XX:+UseNUMA(G1/ZGC 支持)

8.3 HPC

# MPI 进程绑 NUMA
mpirun --map-by numa --bind-to core ./simulation

8.4 容器

Kubernetes topology-manager(TopologyPolicy: best-effort / restricted / single-numa-node)保证 pod 的 CPU 和内存在同一 node。

九、诊断

numastat            # per-node hit/miss/foreign
numastat -p java    # per-process per-node

perf stat -e node-loads,node-load-misses,node-stores,node-store-misses ./app

cat /proc/$$/numa_maps
# addr policy=default file=/lib/x86_64-linux-gnu/libc.so.6 mapped=123 ...

numa_miss / numa_foreign 高 = 跨 node 访问严重。

十、常见问题

A:MySQL 性能波动大 原因:内核 default policy → buffer pool 全分到启动时的 node → 另一半 CPU 全跨 node。修复:numactl --interleave=all

B:NUMA balancing 导致 CPU 毛刺 大内存 Java 服务 NUMA hint fault 频繁。numa_balancing=0 + 手动绑定。

C:CXL 节点意外参与分配 /sys/devices/system/node/nodeN/memtier 没配好。确认 demotion 顺序。

十一、小结


参考文献

工具


上一篇OOM Killer 下一篇HugeTLB 与 THP

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-07-09 · os

【操作系统百科】可拆分 OS

CXL/RDMA 会把 OS 拆成什么形状?LegoOS 分离式内核、CXL 2.0/3.0 内存池、Far Memory、远程页面错误、failover 语义——本文讲硬件解耦对 OS 的冲击。

2026-07-10 · os

【操作系统百科】OS 的下一个十年

下一代 OS 应为 AI workload、异构计算、CXL、内核旁路做什么?加速器主导的调度、sched_ext + ML、分离执行、OS 与 runtime 的重新分工——以工程案例收束全系列。

2026-05-26 · os

【操作系统百科】spinlock 家族

内核 spinlock 从关中断到 qspinlock 演化了四代。本文讲原始 spinlock、ticket lock、MCS lock、qspinlock、paravirt qspinlock、spin_lock_irqsave 的代价与 NUMA 友好性。

2026-04-27 · os

【操作系统百科】内存回收

Linux 内存回收是 VM 最复杂的子系统之一。本文讲 active/inactive LRU、kswapd 与 direct reclaim、watermark 三线、swappiness 的真实含义、MGLRU 改造、memcg 回收与 PSI。


By .