当前位置: 首页 > news >正文

挑战 Linus 的“禁区”:从 2026 LSFMM+BPF 大会看每 CPU 页表的性能逆袭

引言

在 Linux 内核的高性能网络与内存管理优化中,this_cpu操作一直扮演着核心角色。然而,这项旨在消除锁竞争的设计,在不同的 CPU 架构上却有着截然不同的命运。

2026 年 Linux 存储、文件系统、内存管理和 BPF 峰会(LSFMM+BPF Summit)的内存管理(MM)讨论会期间,内核开发者 Yang Shi 提出了一项针对this_cpu工作原理的根本性修改方案。该方案试图通过引入“每 CPU 页表(per-CPU page tables)”来抹平架构间的性能鸿沟。然而,这一提议不仅颠覆了内核的传统认知,更直接触碰了 Linus Torvalds 曾极力反对的底层“禁区”。

1. 什么是 per-CPU 变量?如何靠它实现“无锁化”?

在多核(SMP)系统中,当多个 CPU 核心同时读写同一个全局变量时,就会引发数据竞争(Data Race)。传统的保护方式是使用自旋锁(Spinlock)或互斥锁(Mutex)。

传统锁机制的代价:缓存颠簸与排队

当 CPU A 加锁修改数据时,CPU B 只能自旋等待。更糟糕的是,锁机制会导致硬件层面的缓存一致性风暴(Cache Invalidation)——数据在不同 CPU 的 Cache Line 之间频繁搬移(即缓存颠簸/Cache Thrashing),这会带来巨大的性能损耗。

per-CPU 变量的魔法:空间换时间

为了彻底干掉锁,Linux 内核引入了per-CPU 变量。它的核心思想极其纯粹:既然大家抢同一个变量会打架,那我就给每个 CPU 核心都复制一份一模一样的变量私有副本。

  • 无锁化原理:当内核代码需要操作某个 per-CPU 变量时,它通过当前执行代码的 CPU 编号(CPU ID)作为索引,直接去访问属于该 CPU 自己的那份内存。

  • 各玩各的,互不干扰:CPU 0 只读写变量的“副本 0”,CPU 1 只读写“副本 1”。因为在空间上完全隔离,根本不存在多核竞争,因此完全不需要加锁

  • 硬件级优化:内核还会确保每个 CPU 的副本都在独立的缓存行(Cache Line)上,避免了假共享(False Sharing),让 CPU 能以接近硬件极限的速度本地访问数据。例如,内核中各个 CPU 的网络收发包计数器、内存分配器的本地缓存(PCP)都极度依赖这种机制。

2. 现状之痛:x86 与 Arm 的天壤之别

虽然 per-CPU 变量在逻辑上实现了无锁,但在具体的汇编指令级实现上,不同 CPU 架构却拉开了巨大的差距。这就是this_cpu操作(专门用于快速访问当前 CPU 私有变量的宏)需要解决的核心问题。

x86 的硬件外挂:段寄存器

在 x86 架构上,每 CPU 访问可以通过在相关指令前加上段寄存器前缀(如gsfs)来实现。

代码段

# x86 汇编示例:一步到位 movl %gs:per_cpu_variable_offset, %eax
  • 优势:MMU(内存管理单元)在硬件层自动处理基地址偏移,这使得整个访问变成了一个单指令操作。由于单指令在单核上天然具备原子性,执行过程中不可能被中断或抢占,安全且极快。

Arm 等架构的无奈:多指令序列

包括 Arm 和 RISC-V 在内的许多现代架构并没有类似于 x86 的段寄存器机制。

  • 劣势:它们必须在软件层分步执行——第一步:获取当前 CPU 的 ID 并计算出地址偏移;第二步:通过计算出的虚拟地址去读写数据。这直接将一个原本简单的操作变成了多指令序列

性能的牺牲者:抢占(Preemption)

多指令序列带来了一个致命的并发漏洞:如果线程在第一步(计算出地址)之后、第二步(尚未读取数据)之前被内核抢占,或者该线程被调度迁移到了另一个 CPU 上,那么当它恢复执行第二步时,它访问的依然是旧 CPU 的数据(导致 Data Corruption)。

为了堵住这个漏洞,Arm 等架构在执行this_cpu操作时,必须显式地禁用内核抢占(Disable Preemption)。频繁地关闭和开启抢占,成为了非 x86 架构上的一大性能包袱。

3. Yang Shi 的破局方案:每 CPU 页表与双重映射

为了彻底消除 Arm 等架构上的地址计算开销与禁用抢占的包袱,Yang Shi 提出了一个大胆的设想:利用 MMU 的页表黑魔法,让同一个内核虚拟地址在不同的 CPU 上自然指向不同的物理内存。

其核心设计包含以下几个要点:

  • 消除索引计算:通过动态配置每 CPU 页表,任何给定的每 CPU 变量在所有 CPU 核心上都拥有完全相同的虚拟地址(例如都是0xffff888000001000)。CPU 访问时直接读写该地址即可,硬件会自动映射到不同的物理页。由于不需要计算偏移,抢占自然也不再是问题。

  • 双重映射(Dual Mapping)解决初始化难题:由于变量在各 CPU 上的虚拟地址相同,这会破坏用于跨 CPU 初始化数据的per_cpu_ptr()宏(该宏需要能遍历所有 CPU 的数据)。为此,Shi设计了双重映射机制:

    1. 全局映射:保留现有的全局内核映射,专门用于跨 CPU 的初始化与全局管理。

    2. 私有映射:针对每个 CPU 建立特定的每 CPU 页表映射,用于日常的高速无锁访问。

4. 为什么 Linus Torvalds 曾强烈反对这种设计?

正如与会的 Jason Gunthorpe 所指出的,使用每 CPU 页表并不是什么新发明。在过去,Linux 掌门人 Linus Torvalds 曾对此类方案持强烈反对态度。如果无法妥善解决 Linus 的顾虑,这项特性将很难被合并进主线。

Linus 的极力反对,主要基于以下三大“工程梦魇”:

① TLB(转译后备缓冲器)的管理灾难

页表的核心加速器是 TLB(页表缓存)。在传统设计中,内核地址空间在所有 CPU 间是共享且全局(Global)的。

如果引入每 CPU 页表,意味着同一虚拟地址在不同 CPU 上对应不同的物理页。一旦某个每 CPU 变量被释放或内核动态调整了内存映射,内核就必须极其精确地发起TLB 刷新(TLB flush)。在庞大的多核系统上,管理这种“因核而异”的内核 TLB 条目极易出错,稍有不慎就会引发难以调试的硬件级内存损坏(Stale TLB entries)。

② 多核扩展性死锁(IPI 频繁)

Linus 一向对任何可能导致多核扩展性暴跌(Scalability issue)的设计高度警惕。如果每个 CPU 都有自己独立的内核页表副本,那么当内核动态分配、释放内存,或者修改了全局内核地址空间时,内核就必须把这些修改同步复制到所有 CPU 的页表中。在动辄上百核的服务器上,这会引发大量的处理器间中断(IPI)和严重的锁竞争,得不偿失。

③ 历史阴影:32位时代的kmap_atomic

内核历史上吃过类似的亏。在 32 位 x86 时代,为了访问高于 1GB 的内存(Highmem),内核引入了kmap_atomic。它也是为每个 CPU 保留一组专用的页表条目来进行临时映射。这个机制后来成为了内核维护者的噩梦,代码晦涩、死锁频发。Linus 极其厌恶这种在内核态“动态倒腾页表”的设计。

5. 2026 的技术天平:不可忽视的庞大收益

既然有如此大的历史阻力,为什么 Yang Shi 依然选择在 2026 年旧事重提?答案在于硬件的演进无法拒绝的性能跑分

成本在可控范围内

随着现代处理器架构的迭代,硬件对 TLB 的管理(如 ARM 的 ASID/PCID 进程上下文 ID 匹配机制)已经大幅改善。Shi 指出,该方案的内存开销极小:在具有160 个核心的大型机器上,每 CPU 页表仅需占用约2MB的物理内存。虽然它确实会带来额外的页表分配操作,且在 32 位老旧架构上可能存在虚拟地址空间紧张的问题,但在如今 64 位服务器主导的时代,这些副作用已不再致命。

惊艳的基准测试结果

在 160 核 Arm 系统上跑出的性能数据,让会场上的专家们(如 Brendan Jackman)大为震惊:

  • 内核构建基准测试(Kernel-build):系统时间(System Time)大幅减少了13-18%,实际执行时间(Wall-clock Time)缩短了3-7%

  • stress-ng 基准测试:同样展现出了极为显著的性能压制。

如此庞大的系统级时间红利,单靠 Mini 避免禁用抢占是解释不通的,任何涉及多于一条指令的更新类型操作,仍然需要在禁用抢占的情况下执行。背后必然还涉及到了更深层次的 CPU 流水线指令深度优化和缓存命中率改善,这使得内核社区不得不重新严肃审视该方案。

6. 未来展望与替代路径

随着会议进入尾声,开发者们针对该方案的未来和替代方案展开了激烈的头脑风暴:

  • 内核内可重启序列(Restartable Sequences):Ryan Roberts 提出,由 Peter Zijlstra 主导的内核内rseq工作是否能作为无锁多指令序列的替代方案?由于 Shi 对此尚不深入,这成为了后续的研究方向。

  • NUMA 文本复制(NUMA Text Replication):Shi 指出,一旦每 CPU 页表的框架搭建成功,未来还可以顺理成章地用于在不同的 NUMA 节点之间复制内核核心代码文本(Kernel Text),实现真正意义上的全系统本地高速访问。

  • 联动 “mermap”:Brendan Jackman 也兴奋地表示,每 CPU 页表的引入将完美助力他此前在大会上提出的 “mermap” 内存映射优化提案。

结语

在 Linux 内核的长青树下,没有什么是不可动摇的,即使是 Linus 曾经给出的定论。Yang Shi 的这项提案,正是现代多核 ARM 服务器兴起背景下,底层架构对绝对性能的一次勇敢突围。在 13-18% 的巨大系统级优化面前,内核社区究竟会通过精妙的工程手段驯服 TLB 刷新的恶魔,还是寻找更温和的替代方案?让我们拭目以待这场 2026 年内核最精彩的架构变革之争。

http://www.jsqmd.com/news/980332/

相关文章:

  • 质谱分子识别中的跨模态对比学习技术解析
  • 一体化水文水质监测设备:水域环境常态化监测
  • 住宅IP怎么用?手把手教你做广告地域验证(附代码)
  • AI内容检测实战:对抗扰动下的鲁棒性检测框架
  • 老旧服务器焕发第二春:在CentOS 7最小化安装上跑起OpenStack私有云
  • 从零到一:手把手教你用Qt和QScada框架搭建一个简易的工业监控界面(保姆级教程)
  • 2026年透明背景PNG图片制作方法 去除背景换成透明效果的完整指南
  • Jupyter工作流本质:Kernel、Server与Frontend三系统协同原理
  • anniversary
  • 生产级机器学习系统:从模型部署到系统韧性工程
  • PilotTTS 本地一键整合包发布!8G显存玩转超长文本+情绪控制(附阅读APP接入教程)
  • 机器学习模型生产就绪:从Notebook到高可用服务的七条铁律
  • RPA 在人事部门的深度落地
  • 遗传算法工程实践指南:从参数调优到动态算子设计
  • AI建站工具选型指南:3大维度对比,找到最适合你的那个
  • 2026年6月深耕商事争议解决:西宁董新春律师结合近年建材业典型案例,谈合同条款细节与物流单据在诉讼中的致命作用 - 十大排行榜推荐
  • Sqribble:面向文档自动化的模板驱动型操作系统
  • 告别应用商店限制:手动下载安装Win11安卓子系统(WSA)最新版全攻略
  • 别再为Pytorch3D安装掉头发了!Ubuntu 18.04/20.04保姆级避坑指南(含CUDA 11.x适配)
  • 样本选择偏差:为什么按结果变量筛选样本会让 OLS 有偏?
  • AI Agent如何解决传统自动化失败的三大根本问题
  • 零基础极速上手:10分钟用AI建站工具搭出你的第一个网站
  • 山西干冰厂家直销
  • 乙方验收PPT咋做才能让甲方满意?一份避坑指南
  • 机器学习落地五大不可绕行决策节点
  • RTX 4090上LLaMA 2与LLaMA 3微调实测:显存、温度与梯度流关键瓶颈解析
  • [STM32]Day9-Part2串口收发数据包
  • Codex桌面版接入Deepseek api key教程
  • LLM生产系统合规落地:分层治理架构与工程实践
  • 多维聚合本质:维度建模、粒度对齐与语义锚点