首页/系统/Linux 内核与性能调优速查/set_mempolicy 与 mbind 应用级 NUMA 策略
内存与 OOM58 条

set_mempolicy 与 mbind 应用级 NUMA 策略

应用可通过系统调用设置 NUMA 内存策略:MPOL_DEFAULT 默认、MPOL_BIND 绑定节点、MPOL_PREFERRED 优先、MPOL_INTERLEAVE 交错分布。

应用级 NUMA 策略

应用可以通过系统调用自行设置 NUMA 内存策略:set_mempolicy 作用于调用线程之后的分配,mbind 作用于指定的内存区间。常用策略有 MPOL_DEFAULT(沿用默认)、MPOL_BIND(只从指定节点分配)、MPOL_PREFERRED(优先指定节点但允许兜底)、MPOL_INTERLEAVE(在多个节点间交错,提升带宽利用率)。策略按线程生效且可被继承,线程池应用要留意策略是否被带到其他工作线程。

基本信息

接口set_mempolicy(2) 与 mbind(2)
作用域set_mempolicy 为线程级,mbind 为内存区间级
主要策略DEFAULT、BIND、PREFERRED、INTERLEAVE
观测numastat -p <pid> 看进程的节点分布
命令行封装numactl 提供等价的启动方式

典型使用场景

  • 内存带宽受限的服务用交错分配摊开访问
  • 确定性要求高的服务需要绑定到单一节点
  • 排查线程池中部分线程跨节点访存的问题
  • 与 numactl 命令行方案做对比选择
  • 大页与 NUMA 策略组合使用时评估效果

C 调用片段

C 调用片段
unsigned long mask = 1UL << 0;                       // 位图表示节点集合
set_mempolicy(MPOL_BIND, &mask, 64);                 // 之后的内存分配绑定 0 号节点
unsigned long mask2 = (1UL << 0) | (1UL << 1);
mbind(addr, len, MPOL_INTERLEAVE, &mask2, 64, 0);    // 该区间在两个节点间交错
numactl -H | head -20                                # 先确认节点与核的拓扑
numastat -p <pid>                                    # 观察进程实际落在哪些节点
numactl --hardware | grep -E 'node|size'

策略对照

策略含义适用场景
MPOL_DEFAULT沿用线程或系统默认没有特殊访存要求
MPOL_BIND只从指定节点分配要求确定性、避免跨节点访问
MPOL_PREFERRED优先指定节点,允许兜底希望就近但不愿意分配失败
MPOL_INTERLEAVE在多个节点间交错分配带宽密集型负载,避免单节点争抢
策略按线程生效并可被继承:线程池创建新线程时应显式重设,否则可能继承到不该有的节点绑定。
BIND 策略下节点内存不足会直接导致分配失败,而不是回退到其他节点;应与备用节点、监控与容量规划一起考虑。

与命令行方案的取舍

  • numactl 适合在启动时一次性设定,服务化部署时复用简单
  • 应用内调用适合需要按运行阶段或线程粒度调整策略的场景
  • 两者混用时以最后设置的为准,排查时按时间顺序核对生效值

易错点

  • 线程池的策略继承:工作线程沿用了创建者的绑定,部分线程行为异常
  • BIND 没有备用节点:节点内存耗尽时分配直接失败
  • 忘记策略只影响之后的分配:已经分配的页面不会随策略自动迁移
  • 与 numactl 或 cgroup cpuset 叠加冲突:多层设置相互覆盖,结果与预期不符
  • 对小对象使用交错分配:额外开销大于收益,性能反而下降

数据来源与参考

  • man-pages set_mempolicy(2)/mbind(2)
  • Linux 内核 Documentation/admin-guide/mm/numa_memory_policy.rst
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌