引言

在传统的SMP(对称多处理)系统中,所有CPU核心通过一条共享总线访问同一块内存,所有内存访问延迟是均匀的(UMA)。然而,随着CPU核心数量的增加,共享总线成为了巨大的性能和 scalability 瓶颈。为了解决这个问题,NUMA(Non-Uniform Memory Access,非统一内存访问) 架构应运而生。它带来了更高的可扩展性,但也引入了新的复杂性:内存访问速度取决于内存相对于执行CPU的位置。Linux内核必须感知并优化这种架构差异,否则性能将急剧下降。本文将解析NUMA的特点、内核的亲和性调度策略以及跨节点访问的优化手段。

一、 NUMA架构特点:距离产生延迟

NUMA架构的核心思想是将大量处理器分组,每个组成为一个节点(Node)。每个节点包含:

  • 一组CPU核心(通常是一个物理CPU插槽或多个核心的集合)
  • 一片本地内存(Local Memory)
  • 一个内存控制器集成在节点内

节点之间通过高速互连(如Intel的QPI、AMD的Infinity Fabric)连接。

关键特性:
  1. 访问延迟不对称

    • 本地访问(Local Access):CPU访问其所属节点的本地内存,路径最短,速度最快,延迟最低
    • 远程访问(Remote Access):CPU访问其他节点的内存,必须通过节点间互连,速度较慢,延迟更高(通常比本地访问慢1.5到2倍甚至更多)。
  2. 访问带宽不对称

    • 每个节点的本地内存带宽是独享的。
    • 节点间互连的总带宽是有限的,并且被所有节点共享。频繁的远程访问会饱和互连带宽,成为系统瓶颈。

对操作系统的影响:内核的内存分配策略不能再是“随便找一块空闲内存”。它必须尽量保证一个进程所使用的内存,其“归属”与运行该进程的CPU所在节点一致,即遵循节点亲和性(Node Affinity),否则应用程序将遭受性能损失。

二、 节点亲和性调度:将进程绑定在家门口

Linux内核提供了一套强大的机制来保证NUMA亲和性,其目标是 “尽量让任务在分配内存的同一个节点上运行,并尽量在任务运行的节点上为其分配内存”

1. 自动的NUMA平衡

现代Linux内核(CONFIG_NUMA_BALANCING)包含一个重要的后台特性——自动NUMA平衡

  • 工作原理
    1. 跟踪:内核周期性地标记进程的页表项为“未访问”(清除Accessed位)。
    2. 扫描:稍后再次检查这些页。如果发现一个页被频繁访问,但其所在的NUMA节点与当前正在运行的CPU节点不一致,则判定该页存在跨节点访问
    3. 迁移:内核会尝试执行两种迁移:
      • 页面迁移(Page Migration):将“热”的内存页迁移到当前运行的CPU的本地节点。
      • 任务迁移(Task Migration):将进程本身调度到内存页所在的节点上运行。
  • 目标:通过动态迁移,减少远程访问次数,优化运行时性能。这对于不具备NUMA意识的应用程序尤其重要。
2. 手动调度策略与绑定

对于性能要求极高的应用(如数据库、高性能计算),自动平衡可能不够及时或会产生开销。因此内核提供了手动控制的接口:

  • NUMA调度策略:通过set_mempolicy()系统调用或numactl命令,可以设置进程的内存分配策略。
    • MPOL_BIND:严格只在指定的一个或多个节点上分配内存。
    • MPOL_PREFERRED:优先从首选节点分配,失败时再从其他节点分配。
    • MPOL_INTERLEAVE:在指定的多个节点之间交错分配内存页,用于均匀分散内存带宽压力。
  • CPU亲和性(Affinity):通过sched_setaffinity()系统调用或taskset命令,可以将进程或线程绑定(pinning) 到特定的CPU核心上运行。
  • 联合使用:最优策略通常是将进程绑定到一组核心,并设置其内存分配策略与这些核心所在的NUMA节点一致
# 使用 numactl 命令启动一个程序,将其CPU和内存都限制在Node 0
numactl --cpunodebind=0 --membind=0 ./my_app# 使用 taskset 将进程绑定到特定CPU,再通过 numactl 设置内存策略
taskset -c 0-7 numactl --membind=0 ./my_app

三、 跨节点内存访问优化:无法避免时的补救措施

尽管有亲和性策略,但某些场景下跨节点访问仍无法避免(例如,一个节点内存不足)。内核为此提供了多种优化机制。

1. 每节点伙伴分配器

内核并非运行一个全局的伙伴系统。在NUMA系统中,每个节点(Node)都拥有自己独立的struct zone和伙伴分配器(Buddy Allocator)

  • 当在一个节点上请求分配内存时,分配器会首先尝试从当前节点的本地内存中分配。
  • 只有当本地节点内存不足时,才会根据策略 fallback 到其他节点。
  • 这从分配源头就最大限度地保证了内存的本地性。
2. SLAB分配器的每节点缓存

SLAB分配器同样支持NUMA优化。它为每个CPU每个节点都创建了缓存。

  • kmalloc()等函数在分配内存时,会优先从当前CPU所在节点的缓存中获取对象。
  • 这确保了被频繁分配和释放的小对象具有极好的访问局部性。
3. 回退(Fallback)列表

每个NUMA节点都维护一个内存分配回退列表。当本地节点无法满足分配请求时,内核会按照此列表的顺序去尝试其他节点。列表的顺序通常由节点间的距离(Distance) 决定,优先选择更“近”(访问延迟更低)的节点。

4. 负载均衡与Interleave

对于需要巨大内存带宽的应用,如果所有内存都集中在一个节点,其本地内存带宽可能成为瓶颈。

  • Interleave策略:内核的MPOL_INTERLEAVE策略或硬件自带的内存交错功能,可以将连续的内存页轮流分配到多个节点上。
  • 效果:这允许应用程序同时利用多个节点的内存控制器和带宽,从而聚合出比单个节点更高的总带宽。这对于大规模流式处理等场景非常有效,但代价是失去了局部性,所有访问都变成了“远程”。

总结

NUMA架构是高性能计算的基石,但也带来了管理的复杂性。Linux内核通过一套组合策略来应对:

  1. 感知(Awareness):内核清晰地了解系统的NUMA拓扑结构,包括节点、CPU和内存的归属关系以及节点间的距离。
  2. 亲和(Affinity):通过自动平衡手动绑定策略,极力保证任务在其内存所在的节点上运行,最大化本地访问比例。
  3. 优化(Optimization):在架构上采用每节点分配器,在无法避免远程访问时,通过回退列表选择最近的节点,或在需要带宽时采用交错分配

对于系统管理员和开发者而言,理解NUMA意味着:

  • 使用numastat命令监控各节点的内存分配和跨节点访问(numa_miss)情况。
  • 使用numactltaskset对关键应用进行精细化的资源调度的绑定。
  • 在编写程序时,考虑数据局部性,避免线程在CPU间频繁迁移而导致内存访问模式恶化。

掌握NUMA内存管理,是从“让程序能运行”到“让程序在高端硬件上飞起来”的关键一步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/97967.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/97967.shtml
英文地址,请注明出处:http://en.pswp.cn/web/97967.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【论文翻译】Seg-Zero: Reasoning-Chain Guided Segmentation via Cognitive Reinforcement

0. 摘要Traditional methods for reasoning segmentation rely on supervised fine-tuning with categorical labels and simple descriptions, limiting its out-of-domain generalization and lacking explicit reasoning processes. To address these limitations, we propo…

Playwright MCP浏览器自动化教程

你是否曾厌倦在编程软件和浏览器之间反复切换,只为了检查AI生成的代码能否正常运行?现在,有了Playwright MCP(Model Context Protocol),你可以直接让AI自己操作浏览器,查看自己写的代码运行效果…

矩阵中遍历某个点周围的九个点

又是学习新知识的一天,以下为Java版本部分关键代码int[] neighbors {0, 1, -1};int rows board.length;int cols board[0].length;int[][] copyBoard new int[rows][cols];for (int row 0; row < rows; row) {for (int col 0; col < cols; col) {int liveNeighbors…

单例模式:只有一个对象

目录 什么是单例模式 能解决什么问题 使用场景 如何实现 __new__ 方法&#xff1a;经典又直接 装饰器&#xff1a;不改类本身&#xff0c;也能单例 模块本身就是单例 注意事项 总结 你有没有过这样的困扰&#xff1a; “为什么我明明只创建了一次数据库连接&#xff0…

AI大模型学习(6)Yolo V8神经网络的基础应用

Yolo V8神经网络的基础应用2024-2025年最火的目标检测神器&#xff0c;一篇文章让你彻底搞懂&#xff01;&#x1f929;大家好呀&#xff01;今天我们要聊一聊计算机视觉领域的「明星模型」——YOLO神经网络&#xff01;&#x1f3af; 如果你对「目标检测」这个词还比较陌生&am…

C++:imagehlp库

imagehlp库1. 简介2. 主要函数与用途2.1PE 文件解析相关2.2 符号处理相关2.3 崩溃转储相关2.4 版本资源相关3. 使用示例3.1 解析内存地址对应的函数名和行号3.2 创建目录使用示例1. 简介 imagehlp 是 Windows 系统提供的一个图像处理与调试辅助 API 库&#xff08;Image Helpe…

如何在Anaconda中配置你的CUDA Pytorch cuNN环境(2025最新教程)

目录 一、简介 二、下载CUDA 三、下载Pytorch-GPU版本 四、下载CUDNN 五、总结 六、测试代码 一、简介 啥是Anaconda?啥是CUDA?啥是CUDNN&#xff1f;它们和Pytorch、GPU之间有啥关系? 怎么通俗解释它们三者的用途和关系&#xff1f; 1.GPU(图形处理单元&#xff09…

算法面试(1)-----目标检测和图像分类、语义分割的区别

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 目标检测&#xff08;Object Detection&#xff09;、图像分类&#xff08;Image Classification&#xff09;、语义分割&#xff08;Semantic Segmentation&#xff09; 是计算机视…

电脑散热风扇有噪音怎么解决

一、初步检查与清理断电并拆机关闭电脑并拔掉电源&#xff0c;打开机箱侧板&#xff08;笔记本需先拆除后盖螺丝&#xff09;。操作前建议佩戴防静电手环&#xff0c;避免静电损坏硬件。清理风扇及散热片灰尘使用压缩空气罐从风扇进风口吹走灰尘&#xff0c;或用软毛刷轻轻刷去…

SeaweedFS深度解析(九):k8s环境使用helm部署Seaweedfs集群

上一篇&#xff1a;《SeaweedFS深度解析&#xff08;八&#xff09;&#xff1a;k8s环境使用Operator部署Seaweedfs集群》 链接: link #作者&#xff1a;闫乾苓 文章目录k8s环境使用helm部署Seaweedfs集群准备镜像seaweed-master-localpv-storageclass.yamlseaweed-volume-lo…

MATLAB绘制一个新颖的混沌图像(新四翼混沌系统)

新四翼混沌系统:dx/dt a(y - x) yz dy/dt cx - y - xz dz/dt -bz xyMATLAB代码:function plot_novel_chaotic_system() % 参数设置 a 10; b 8/3; c 28;% 初始条件 x0 [1, 1, 1];% 时间范围 tspan [0 100];% 求解微分方程 [t, x] ode45((t, x) chaotic_system(t, x, …

金融数据---获取股票日线数据

获取股票日线的数据方式有很多&#xff0c;包括东方财富&#xff0c;同花顺&#xff0c;tushare&#xff0c;这里我们就利用东方财富的数据&#xff0c;是免费的开源获取&#xff0c;第一步先安装akshare&#xff0c;pip安装就可以py -m pip install akshareAkshare 股票数据获…

Mac 真正多显示器支持:TESmart USB-C KVM(搭载 DisplayLink 技术)如何实现

多显示器已经不再是奢侈品&#xff0c;而是专业人士提升生产力的必需工具。无论是创意设计师、股票交易员还是软件开发人员&#xff0c;多屏幕都能让工作流程更高效、更有条理。 然而&#xff0c;Mac 用户长期以来面临一个主要障碍&#xff1a;macOS 原生不支持多流传输&#x…

【实时Linux实战系列】静态链接与libc选择:musl vs glibc的时延权衡

背景与重要性 在实时系统开发中&#xff0c;选择合适的C标准库&#xff08;libc&#xff09;和链接方式对系统的启动时间、线程性能和内存分配效率有着显著影响。glibc和musl是两种流行的C标准库实现&#xff0c;它们在设计目标和性能表现上存在差异。通过对比这两种libc在启动…

Altium Designer(AD24)的三种文件组织形式,工程文件,自由文件与存盘文件

🏡《专栏目录》 目录 1,概述 2,工程文件 3,自由文件 4,存盘文件 5,文件转换 5.1,工程文件于自由文件互转换 5.2,工程文件于存盘文件互转换 6,注意事项 1,概述 本文介绍Altium Designer 24软件(后文简称AD24或软件)的三种文件组织形式,工程文件,自由文件和存盘文…

Python+Selenium实现自动化测试

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快安装selenium打开命令控制符输入&#xff1a;pip install -U selenium火狐浏览器安装firebug&#xff1a;www.firebug.com&#xff0c;调试所有网站语言&#xff0…

2024年CSP-X初赛真题及答案解析(6-10)

2024年CSP-X初赛真题及答案解析(6-10) 字符串abcabcabc有多少不同的非空子串?( )。 A. 24 B. 36 C. 45 D. 46 答案:A 解析: 长度 1: 3 个(a, b, c) 长度 2: 3 个(ab, bc, ca) 长度 3: 3 个(abc, bca, cab) 长度 4: 3 个(abca, bcab, cabc) 长度 5: 3 个(a…

缓存与数据库一致性的4大坑及终极解决方案

缓存雪崩、击穿、穿透全中招&#xff1f;别让缓存与数据库的“爱恨情仇”毁了你的系统&#xff01; 你有没有经历过这样的深夜告警&#xff1a;Redis 响应延迟飙升&#xff0c;数据库 CPU 直冲 100%&#xff0c;接口大面积超时&#xff1f;一查日志&#xff0c;发现大量请求绕过…

基于 Python charm 库实现的一些 Pairing 密码学算法

基于 Python charm 库实现了一些 Pairing 密码学算法&#xff0c;放在了 https://github.com/BatchClayderman/Cryptography-Schemes 里面。 在正确部署了 Python charm 库后&#xff0c;所有的 Python 脚本都是独立的&#xff0c;即该存储库中不存在一个脚本调用另一个脚本的…

用户体验五大要点:从问题到解决方案的完整指南

在互联网产品设计和运营的过程中&#xff0c;用户体验&#xff08;User Experience&#xff0c;简称 UX&#xff09; 已经成为决定产品成败的关键因素。一个功能再强大的产品&#xff0c;如果用户用得不舒服、不信任&#xff0c;甚至觉得没有价值&#xff0c;最终都会被抛弃。那…