基于机器学习的NUMA优化:提升大规模集群性能与资源效率
1. 项目概述:当NUMA遇上机器学习,我们如何为十万台服务器“减负”
在数据中心里,每一微秒的延迟和每一瓦特的功耗都至关重要。如果你管理过大规模在线服务集群,尤其是像搜索、推荐这类对延迟极其敏感的业务,你一定对“性能抖动”深恶痛绝。很多时候,问题的根源并非代码逻辑,而是深藏在硬件架构层面——比如,非统一内存访问,也就是NUMA。
NUMA架构是现代多路服务器提升内存带宽和扩展性的基石。简单来说,它把CPU和离它最近的那部分内存捆绑成一个“节点”。CPU访问自己节点上的内存(本地访问)很快,但要是需要访问其他节点的内存(远程访问),就得通过CPU之间的互联总线“绕个远路”,延迟和带宽都会打折扣。想象一下,在一个大型开放式办公室里,你伸手就能拿到自己工位上的文件(本地访问),但要是需要隔壁部门同事桌上的文件(远程访问),你就得起身走过去,甚至要等别人传过来,效率自然就低了。
在百度这样拥有数十万台服务器、运行着成千上万种不同特性工作负载的“超大规模计算集群”里,NUMA带来的挑战被急剧放大。传统的优化手段,比如Linux内核自带的AutoNUMA,依赖于动态的线程和内存页迁移。但在我们的生产环境中观察发现,很多在线服务的线程生命周期极短(毫秒级),频繁的迁移导致AutoNUMA的优化效果大打折扣,平均本地内存访问率仅能提升到57%左右,远未达到理想状态。更棘手的是,盲目进行大规模内存页迁移,其本身带来的开销(CPU占用、时间延迟)在追求极致稳定性的生产环境中往往是不可接受的。
因此,我们与英特尔合作,研发并落地了MAO系统。它的核心思路不是“蛮干”,而是“巧干”:利用机器学习,为每一个工作负载进行“体检”和“预判”。我们不再对所有服务一刀切地进行NUMA绑定,而是先通过一个离线训练的“NUMA敏感性模型”评估绑定可能带来的收益,只对那些收益显著的服务实施精准优化。同时,结合在线的动态监控和资源调度,在提升局部性的同时,避免因绑定造成的服务器内部资源利用不均衡。这套系统上线一年,已覆盖超十万台服务器,在核心的Feed推荐业务中,平均延迟降低了12.1%,同时节省了9.8%的CPU资源。这不仅仅是几个百分点的提升,对于日均千亿次请求的体量而言,意味着巨大的成本节约和用户体验改善。
2. 核心挑战与设计思路:为什么传统方法在大规模集群中“失灵”
在深入MAO的细节之前,我们必须先理解在超大规模生产环境中进行NUMA优化所面临的独特复杂性。这绝非在单机或小集群上做实验那么简单。
2.1 生产环境的四大“顽疾”
第一,工作负载的极端异构性。我们的集群同时运行着从计算密集型(如模型推理)到内存带宽密集型(如数据预处理),再到内存延迟敏感型(如缓存服务)的各类服务。它们的性能特征和对NUMA架构的敏感度天差地别。一种固定的优化策略无法适用于所有场景。
第二,线程行为的“短平快”。通过内核调度跟踪我们发现,大量在线服务线程的活跃时间窗口在0.4毫秒到10毫秒之间。这意味着线程频繁地在CPU核心间迁移以维持系统级的负载均衡。AutoNUMA这类基于“热点页面”分析的迁移策略,其决策和迁移速度可能还赶不上线程迁移的速度,导致刚迁过来的内存页,因为线程被调度走了,瞬间又变成了“远程页”,优化效果被严重稀释。
第三,混合部署带来的资源干扰。为了提升资源利用率,我们的服务器普遍采用高密度的混合部署,即一台物理机上会同时运行来自不同业务、不同服务的多个容器实例。即使有容器隔离技术,底层硬件资源(如最后一级缓存、内存控制器、互联总线)的争用依然存在。为一个实例进行NUMA绑定,可能会加剧其所在NUMA节点上其他实例的资源竞争,或者导致另一个节点资源闲置,造成“旱的旱死,涝的涝死”的资源碎片化问题。
第四,优化开销的严格红线。任何在生产环境部署的优化方案,其自身开销必须极低,且不能引入不可预测的性能抖动。我们实测发现,迁移2GB的内存页,需要一个2.7GHz的CPU核心满负荷工作超过1秒。对于追求99.99%以上可用性的在线服务,这种级别的扰动是灾难性的。因此,我们必须寻找比内存页迁移更“轻量”的干预手段。
2.2 MAO的设计哲学:感知、预测、动态平衡
面对上述挑战,MAO的设计摒弃了“静态绑定”或“盲目迁移”的思路,转向一个数据驱动、动态决策、闭环反馈的体系。其核心设计哲学可以概括为三点:
从“页迁移”转向“线程/进程绑定”:既然内存页迁移开销大且易失效,我们选择更稳定、开销几乎为零的NUMA节点绑定(通过cgroup/cpuset实现)。将整个进程(容器)的内存分配和线程调度限制在特定的NUMA节点内,从根本上保证其内存访问的局部性。这好比给一个项目团队分配一个独立的办公区域,所有资料都在区域内,避免了跨部门取件的耗时。
从“经验规则”转向“模型预测”:不是所有服务都适合绑定。绑定了不敏感的服务,可能白浪费资源灵活性。因此,我们构建了一个机器学习模型(NUMA敏感性模型),用于量化预测对一个特定工作负载进行NUMA绑定能带来多少性能收益。只有预测收益高的服务,才会被列入优化候选名单。
从“单点优化”转向“全局协调”:绑定策略不是一成不变的。MAO的在线优化器会持续监控每个服务器节点内各NUMA节点的负载情况。当发现因绑定导致节点间负载严重失衡(例如一个节点CPU利用率90%,另一个仅50%)时,它会智能地选择解除部分低优先级或收益已饱和实例的绑定,让调度器可以将新的负载调度到空闲资源上,从而实现集群整体资源利用率与单个服务性能的平衡。
这套“离线建模筛选 + 在线动态调控”的组合拳,使得MAO能够适应大规模生产环境中负载的动态性、多样性,在提升性能的同时,保障了集群的整体效率。
3. MAO系统架构深度解析:双模块协同的智能优化引擎
MAO的整体架构清晰地区分为离线分析和在线优化两大模块,两者通过数据流形成闭环。下图勾勒了其核心组件与协作关系:
[ 离线分析模块 ] <-- 性能数据流 --> [ 在线优化模块 ] | | v v [NUMA状态数据库] <-- 模型参数 --> [集群调度器 Matrix Scheduler] | | v v [敏感性模型训练] [节点代理 Matrix Agent] | | v v [服务收益预测] -- 优化建议 --> [资源优化器 Optimizer] | v [资源分配器 Allocator] | v [监控器 Monitor] --> (性能计数器)3.1 在线优化模块:生产环境的实时“指挥官”
在线模块是MAO作用于生产环境的直接手段,它嵌入在百度的集群管理系统“Matrix”中,包含以下关键组件:
3.1.1 监控器:数据的“眼睛”
一切智能决策的基础是数据。监控器部署在每台服务器上,以容器为粒度,持续采集关键的硬件性能计数器数据。我们主要依赖Intel的Resource Director Technology (RDT)和内核的resctrl文件系统,通过Cgroup进行隔离和统计。核心监控指标包括:
| 指标 | 采集目标 | 工具/方法 | 说明 |
|---|---|---|---|
| 内存带宽 | 容器级 | Intel RDTmbm_total_bytes | 反映工作负载对内存带宽的需求压力。 |
| 内存停滞周期 | 容器级 | Intel RDTmbm_local_bytes等计算得出 | CPU等待内存访问完成的周期数,直接关联延迟。 |
| 远程内存带宽比 | 容器级 | 通过RDT分别获取本地/远程带宽计算 | 关键指标:远程访问带宽占总带宽的比例,直接衡量NUMA非局部性。 |
| 内存页面布局 | 进程级 | 解析/proc/[pid]/numa_maps | 获取常驻集(RSS)中各NUMA节点的页面分布,区分文件页与匿名页。 |
| CPU/内存利用率 | 容器级 | Cgroupcpuacct.stat,memory.stat | 基础资源使用情况。 |
实操心得:采集频率需要平衡精度与开销。我们设置为秒级采样,并通过滑动窗口计算均值,既能捕捉到负载变化趋势,又将单个监控线程的CPU开销控制在0.5%以内。对于
/proc文件系统的读取,要注意避免频繁打开关闭带来的性能冲击。
3.1.2 分配器:策略的“执行者”
分配器的职责很简单:根据指令,执行NUMA绑定或解绑操作。我们采用Linux的cgroup v1的cpuset控制器来实现。当需要将一个容器绑定到NUMA节点N时,分配器会:
- 将容器的
cpuset.cpus设置为节点N对应的CPU核心列表。 - 将容器的
cpuset.mems设置为节点N对应的内存节点ID。 这样,该容器内所有进程的线程调度和内存分配(遵循“首次接触”策略)都会被限制在该NUMA节点内。
3.1.3 优化器:动态的“大脑”
优化器是在线模块中最具智能的部分,它周期性运行(如每分钟),负责根据实时数据做出绑定/解绑决策。其工作流是一个典型的控制循环:
- 获取状态:从监控器获取本节点所有容器及NUMA节点的资源利用率(CPU、内存带宽等)。
- 判断解绑条件:检查是否存在因NUMA绑定导致的节点间负载严重失衡。我们采用了比初期更精细的策略B:
- 条件1(失衡):任一NUMA节点的CPU利用率比同节点其他NUMA节点的平均利用率高出15%以上(阈值可调)。
- 条件2(热点):该高负载节点的CPU利用率超过了其历史P95水位线。
- 条件3(过载):绑定在该节点上的某个容器的CPU使用率超过了其申请配额(即 >100%)。 只有同时满足这三个条件,优化器才会触发对该容器的解绑操作,释放其灵活性,允许集群调度器将其部分负载迁移到其他节点。
- 判断绑定条件:对于未被绑定、且被离线模型标记为“高NUMA敏感性”的服务实例,优化器会检查目标NUMA节点是否有足够的剩余资源(CPU、内存),并在资源充足时触发绑定操作。
- 执行与反馈:将绑定/解绑指令下达给分配器执行,并将执行结果及后续的性能变化数据反馈给离线分析模块,用于模型迭代。
避坑指南:解绑策略的阈值设置非常关键。初期我们采用策略A(仅看容器是否过载和节点是否繁忙),导致解绑操作过于频繁,破坏了优化效果。策略B引入了“相对失衡”和“历史水位”概念,更稳定。核心原则是:避免频繁震荡,只在资源矛盾确实突出时进行干预。
3.2 离线分析模块:模型训练的“参谋部”
离线模块的核心任务是构建并持续优化那个能判断“谁适合NUMA优化”的机器学习模型。
3.2.1 NUMA状态数据库
这是一个时间序列数据库,存储了从所有在线监控器汇聚来的海量性能数据。数据按服务(Service)粒度进行聚合,因为同一服务的不同实例通常具有相似的性能特征。这个数据库不仅服务于模型训练,也为运维人员提供了全局的NUMA性能视图。
3.2.2 NUMA敏感性模型:特征工程与训练
这是MAO系统的灵魂。我们定义了一个工作负载的“NUMA敏感性”为:对其进行NUMA绑定后,所能获得的潜在性能提升百分比(如延迟降低)。我们的目标是找到一组能够预测这个“敏感性”的、可在线测量的性能指标。
经过大量实验和分析,我们最终筛选出四个核心特征:
- 内存带宽:工作负载消耗的内存带宽总量。带宽需求越高,远程访问带来的绝对性能损失可能越大,优化收益潜力也越大。
- 内存停滞周期比:
内存停滞周期 / CPU非停机周期总数。这个比值直接反映了内存子系统成为性能瓶颈的严重程度。比值越高,说明工作负载“等内存”的时间越长,改善内存访问延迟(即NUMA优化)的收益可能越明显。 - 非页缓存内存比:
常驻匿名页 / 总常驻内存。Linux中,文件缓存(page cache)的页面是由内核全局管理的,其位置对应用不透明,NUMA优化对其效果有限。而匿名页(如堆、栈内存)是应用直接分配的,是NUMA绑定的主要优化对象。这个比值越高,说明可被有效优化的内存比例越大。 - 远程内存带宽比:
远程内存带宽 / 总内存带宽。这是最直接、最重要的特征。它实时量化了当前不优化状态下的“非局部性”程度。这个值越高,说明工作负载正在忍受越多的远程访问,NUMA绑定的收益预期也就越高。
我们采用XGBoost回归模型来学习这四个特征与“性能提升百分比”之间的复杂非线性关系。选择XGBoost是因为它在处理表格数据、特征重要性评估以及防止过拟合方面表现非常出色,且训练和预测效率高。
模型训练流程:
- 数据收集:在线上小范围、安全地对一批多样化的服务实例实施NUMA绑定,并收集绑定前后上述四个特征值的变化,以及关键的业务性能指标(如平均延迟、QPS)的变化率,形成“特征-收益”样本对。
- 数据预处理:清洗异常值,进行特征标准化。
- 训练与验证:将样本按85%/15%分为训练集和测试集。使用
GridSearchCV进行超参数调优,寻找最优的树深度、学习率等参数。 - 模型评估:我们对比了XGBoost、随机森林和线性回归。结果XGBoost的R²分数达到0.92,平均绝对误差仅为2.5%,预测准确性显著优于其他模型。线性回归效果很差(R²=0.19),这证实了NUMA敏感性与性能指标之间是非线性关系。
训练好的模型会输出每个服务的“预测收益值”。在线调度器会根据这个值,优先对高收益服务进行NUMA绑定推荐。
4. 生产部署与效果验证:从模型到真实的性能提升
任何系统级的优化,最终都要用生产环境的真实效果来说话。MAO的部署采用渐进式、非侵入式的策略,确保业务稳定。
4.1 部署与开销控制
MAO的各个组件以DaemonSet或Sidecar的形式部署,无需重启主机或业务容器。我们对每个组件的资源开销进行了严格评估:
- 监控器:PMU监控开销约0.06%单核,NUMA相关指标监控约0.48%单核,总计约0.5%单核,完全可接受。
- 优化器:每轮决策执行时间小于1毫秒,平均CPU开销约9.4%单核。
- 分配器/调度器通信:开销可忽略不计。 整个系统的额外开销被控制在极低水平,符合生产环境“观测开销不过1%”的严苛要求。
4.2 性能收益分析
我们在核心的Feed推荐和搜索业务中进行了大规模部署,覆盖超过1.27万台服务器。以下是优化后的效果对比:
Feed推荐业务(关键模块):
| 服务模块 | 平均延迟降低 | CPU资源节省 |
|---|---|---|
| Predictor1 | 10.1% | - |
| Predictor2 | 11.72% | - |
| Router | 2.8% | - |
| Feature Service | 23.8% | - |
| 整体平均 | 12.1% | 9.8% |
搜索业务:
- 平均延迟降低:8.6%
- CPU资源节省:6.7%
除了业务指标,微架构层面的改善同样显著:
- 本地内存访问率:平均提升17.26%。这意味着更多的内存请求无需经过慢速的互联总线。
- 每周期指令数:平均提升8.8%。由于CPU等待内存的时间减少,其执行效率得到提升。
这些数字的背后,是模型精准筛选的结果。例如,Feature Service模块因其高内存带宽和初始的高远程访问比,被模型预测为高收益目标,实际优化后获得了最大的延迟提升。而Router模块本身对内存延迟不敏感,预测收益低,因此优化效果相对有限,这反而证明了模型筛选的有效性,避免了无效优化。
4.3 模型预测准确性验证
我们将模型在300个未见过的测试样本上进行预测,并将预测的延迟提升与实测提升进行对比。XGBoost模型表现出色:
- 平均绝对误差:仅2.5%。
- 误差分布:超过90%的样本预测误差在5%以内。
下图展示了预测值与真实值的对比情况,点越靠近对角线y=x,说明预测越准。可以看到,XGBoost模型的预测点紧密分布在对角线两侧,而线性回归模型的点则非常分散,完全无法拟合。 (此处为文字描述,实际报告中会附上散点对比图) 这充分证明了我们基于MBW、RMBR等四个特征构建的NUMA敏感性模型,能够可靠地用于生产环境中的优化决策。
5. 常见问题、排查技巧与未来展望
5.1 实战中遇到的典型问题与解决方案
问题一:绑定后,服务性能不升反降。
- 排查思路:
- 检查资源争用:使用
perf或rdt工具监控绑定后该NUMA节点上所有容器的内存带宽利用率和缓存未命中率。很可能该节点上存在另一个高带宽需求的服务,导致内存控制器或总线成为瓶颈。MAO优化器的解绑逻辑应能检测并缓解此问题。 - 检查模型特征:回顾该服务绑定前的四个特征值。如果其“非页缓存内存比”很低(例如<30%),说明其内存大部分是文件缓存,NUMA绑定收益本就有限。此时性能波动可能是噪声。
- 检查跨节点通信:如果服务本身需要频繁与其他节点上的服务进行RPC调用,绑定可能增加了网络栈处理的局部性,但影响不大。主要看业务指标是否达标。
- 检查资源争用:使用
- 解决方案:通过优化器的监控,确认是否存在资源争用。如有,可考虑调整混合部署策略,或将竞争服务调度到不同节点。对于低NPMR的服务,可将其从NUMA绑定白名单中移除。
问题二:节点间负载出现严重不均衡,一个节点快满了,另一个却很闲。
- 排查思路:
- 确认触发条件:查看优化器日志,确认是否因满足“解绑三条件”而触发了操作。检查负载不均衡的阈值设置(如15%)是否适合当前集群的负载模式。
- 分析负载类型:分析高负载节点上的服务是否都是计算密集型(CPU-bound)。NUMA优化主要解决内存访问问题,对纯计算型负载优化效果有限,却占用了绑定的CPU资源。
- 解决方案:这是MAO优化器设计要解决的核心问题。确保优化器策略B已启用,它会自动将低优先级或已过载实例解绑,让集群调度器重新平衡负载。也可以手动调整服务的资源申请(requests/limits),或为不同特性的服务打上标签,供调度器进行更智能的亲和性调度。
问题三:模型预测收益高,但实际部署后收益远低于预期。
- 排查思路:
- 数据漂移:模型训练数据来自于某个时间段的负载快照,但服务本身可能已更新版本或流量模式发生变化。检查当前监控到的四个特征值,是否与训练样本分布有显著差异。
- 干扰因素:检查部署时段内,主机或邻位容器是否有其他干扰活动(如后台备份、日志收集、内核升级等)。
- 测量误差:确认业务性能指标的采集是否准确,是否与模型训练时使用的指标口径一致。
- 解决方案:建立模型的持续学习流水线。定期(如每周)用新的线上绑定样本对模型进行增量训练或微调,使模型适应服务的变化。MAO的离线模块支持这种闭环迭代。
5.2 未来优化方向
MAO的当前版本主要解决了“绑不绑”和“绑了如何平衡”的问题。在此基础上,我们正在探索更深层次的优化:
- 细粒度内存页管理:对于已绑定的服务,其内部仍可能存在少数“热点”内存页被所有线程频繁访问。我们计划在优化器中集成更轻量的“热点页识别与迁移”功能,仅对这部分关键页面进行迁移,进一步压榨性能。这需要与“首次接触”策略和透明大页等特性谨慎协同工作。
- 基于QoS的差异化策略:当前策略主要考虑整体性能收益和资源均衡。未来可以引入服务等级协议优先级,对高SLO(服务等级目标)的服务给予更激进的NUMA绑定保障,对低优先级服务则更倾向于解绑以换取全局资源利用率。
- 异构硬件感知:随着CXL等新互联技术的普及,NUMA拓扑将更加复杂。MAO的模型和策略需要扩展,以理解不同层级的内存(本地DRAM、CXL内存、持久内存)在延迟和带宽上的差异,做出更优的数据放置决策。
最后一点个人体会:在大规模生产环境中做系统优化,最大的挑战往往不是算法本身,而是对复杂、动态、异构环境的理解和掌控。MAO的成功告诉我们,将机器学习的预测能力与传统的系统调度、资源管理相结合,是一种非常有效的路径。它不是一个“银弹”,而是一个“智能调节器”,帮助我们在性能、资源利用率和稳定性这个不可能三角中,找到当前最优的那个平衡点。每一次优化决策,背后都是数据在驱动,这或许就是未来数据中心自动化运维的核心模样。
