Skip to content

필사 모드: CXL 内存分层,内核走到哪一步了 — DAMON 合并了什么,数字又没测到什么

中文
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

引言 — CXL 故事里内核负责的那部分

CXL 硬件的故事,我们已经在让退役的 DDR4 重获新生 — Meta 的 CXL 桥接芯片 Vistara那篇里讲过一次了。那是一份超大规模厂商的落地部署报告——把退役的 DDR4 用 CXL 复活,当成第二层内存来用。

但芯片插上去是一回事,它真正值回票价又是另一回事。CXL 内存在操作系统看来,不过是一个没有 CPU 的 NUMA 节点,而判断哪些页面热、哪些页面冷,再真正把它们搬过去,这整件事都是内核在做。这个判断一旦错了,CXL 就只是一块慢 RAM。

所以本文看的不是硬件,而是跑在硬件之上的代码。我们直接查阅内核源码,确认截至 2026 年 7 月 Linux mainline 到底真正合并了什么,并追溯这个领域被引用的那些数字,看它们在原始出处里精确测量了什么、又没测量什么。先说结论:落地的是零件,方针依然要靠你自己,而且数字越大,附带的方法论往往越少。

内核搬动页面的两种方式

先看地形。在分层内存里搬动页面,mainline 大体有两种机制。

第一,NUMA balancing 的分层模式(NUMAB-2)。 它用访问检测型缺页中断(prot_none)来找热页面,并在进程自身的上下文里执行提升(promotion)——也就是说,提升这个动作和应用程序真正的工作发生在同一个线程上。降级(demotion)则基于 reclaim,由 kswapd 或 direct reclaim 处理。

第二,DAMON 及其之上的 DAMOS。 DAMON 会拉起一个内核线程,每 5ms 采样一次内存访问,每 100ms 把结果交给用户空间。DAMON 的创始人 SeongJae Park 在 LSFMM+BPF 2026 上介绍称,在一般系统上这个开销不到 0.1%。它最早在 5.15 合并进来。DAMOS 是在这些观测结果之上挂载动作的那一层,用于分层的动作是 migrate_hot(提升)和 migrate_cold(降级)。核心区别在于,DAMOS 跑在异步的 worker 线程上。

这个差异后面会变成一个数字回过头来找你。

截至 2026 年 7 月,mainline 里真正落地了什么

我没有依赖发布材料或新闻报道,而是直接查了内核源码。下面是每个特性最早出现的标签,对照 include/linux/damon.h 和文档确认过。

6.11    DAMOS_MIGRATE_HOT / DAMOS_MIGRATE_COLD
        (v6.10 中没有 -> v6.11 出现。SK hynix:Hyeongtak Ji、Honggyu Kim,2024-06-14)
        用于 HMSDK 的 CXL 容量扩展。阈值是人工手动设定的静态值。

6.16    node_mem_used_bp / node_mem_free_bp 配额目标
        (自调优分层,别名 TPP-DAMON。SeongJae Park)

6.17    damos->migrate_dests — 多个目标节点 + 权重
        (Micron:Bijan Tabatabai。仅限虚拟地址空间)

6.19    node_memcg_used_bp / node_memcg_free_bp
        (以 cgroup 为单位的分层。与 Meta 合作)

7.2-rc1 node_eligible_mem_bp
        (Micron:Ravi Jonnalagadda。目前还没有进入任何正式发布的内核)

这里有两点需要指出。

第一,不存在「装上就能用」的分层内核模块。 在 v7.2-rc3 的 mm/damon/Kconfig 里,「tier」这个字符串出现了 0 次。会被构建出来的 DAMON 模块只有 DAMON_RECLAIMDAMON_LRU_SORTDAMON_STAT 这三个,mm/damon/ 目录下也没有 tiering.c。也就是说,mainline 给出的是零件(配额目标 metric、迁移动作、目标权重),把它们组装成一套方针,是用户空间自己的事。

这不是意外,而是计划本身。在自调优分层的 RFC cover letter 里,作者本人写明,会先提交配额目标 metric 那部分,分层模块那部分则「以后」再提交。理由是模块那一侧只假设了两层,而且节点地址范围需要用户自己手动填入,离成品还差得远。而那个「以后」,到 2026 年 7 月为止仍然没有到来。

所以今天想要跑起来,就得像演讲幻灯片里那样,自己手写 damo 命令。

damo start \
  --numa_node 0 --monitoring_intervals_goal 4% 3 5ms 10s \
      --damos_action migrate_cold 1 --damos_access_rate 0% 0% \
      --damos_apply_interval 1s \
      --damos_quota_interval 1s --damos_quota_space 200MB \
      --damos_quota_goal node_mem_free_bp 0.5% 0 \
      --damos_filter reject young \
  --numa_node 1 --monitoring_intervals_goal 4% 3 5ms 10s \
      --damos_action migrate_hot 0 --damos_access_rate 5% max \
      --damos_apply_interval 1s \
      --damos_quota_interval 1s --damos_quota_space 200MB \
      --damos_quota_goal node_mem_used_bp 99.7% 0 \
      --damos_filter allow young \
      --damos_nr_quota_goals 1 1 --damos_nr_filters 1 1 \
  --nr_targets 1 1 --nr_schemes 1 1 --nr_ctxs 1 1

这套配置在节点 0(DRAM)上降级冷页面,以 0.5% 空闲空间为目标;在节点 1(CXL)上提升热页面,以 99.7% 的 DRAM 使用率为目标。设计意图是把 0.5% 和 99.7% 设置成略有重叠,好让提升和降级不至于互相卡住,cover letter 把这两个值作为默认推荐值提出。这个接口并不差,但要说它「装上就能用」,还是有点勉强。

第二,CONFIG_DAMON 并非默认开启。 2025 年 5 月,SeongJae Park 提交了一个默认启用的补丁,理由是主要发行版早已经默认构建了 DAMON,而且内核包体积只会增加约 0.1%,这个补丁进了 6.16-rc1 的合并窗口。然后在 2025 年 6 月 10 日,Linus Torvalds 把它撤回了。提交 aef17cb3d3c4 的正文只有一行——"No, we don't make random features default to being on."

查一下 v7.2-rc3 的 mm/damon/Kconfig 就会发现,config DAMON 现在依然没有 default y。这次撤回一直维持到了现在。

4.43% 这个数字 — 以及它没测到的东西

自调优分层(6.16)身上贴着的数字是 4.42%。读一读原始 RFC cover letter(SeongJae Park,2025-03-19),条件全都写在里面。

测试环境。 一台把 250 GiB 的 DRAM 层和 50 GiB 的 CXL 层,分别以 NUMA 节点 0 和 1 的形式暴露出来的机器。内核是 v6.13,叠加了 2025-03-15 那份 mm 树上的全部 DAMON 补丁以及这个系列本身,并且改动了 mempolicy() 系统调用使其被忽略,好让应用程序原本的 NUMA 优化不会插手进来。工作负载是 DCPerf 的 Taobench 变种,内存大小 340 GiB,预热 2,500 秒,测量 1,440 秒,RSS 在预热期间会长到 270 GiB。每种配置各跑 5 次。

结果表(cover letter 原文)。

Config         Score   Stdev   (%)     Normalized
Baseline       1.6165  0.0319  1.9764  1.0000
Numab_tiering  1.4976  0.0452  3.0209  0.9264
DAMON_tiering  1.6881  0.0249  1.4767  1.0443

自己算一下:1.6881 除以 1.6165 是 1.0443,所以 DAMON 分层是提升了 4.43%;1.4976 除以 1.6165 是 0.9264,所以 NUMAB-2 是下降了 7.36%。(cover letter 的摘要部分写的是 4.42% 和 7.34%,但从它自己的表里算出来的值其实是 4.43% 和 7.36%。一年后的 LSFMM 幻灯片里,"~4.42%" 也原样沿用了下来。这是个小事,但也说明被引用的这个数字,没有经过任何人重新核算原始表格的手。)

到这里为止,听起来都是好消息。现在来看看同一份 cover letter 自己写下的那些附加条件(caveat)。

未改动的工作负载原本什么差异都没有。 照搬作者自己的表述:Taobench 的访问模式非常静态,只有大约 13% 的 RSS 从头到尾被频繁访问,结果就是无论设计和实现是什么,提升(promotion)都没能产生有意义的性能差异。于是作者改了内核,注入了一个扰动——每分钟把最多 10 GiB 的热页面降级、最多 10 GiB 的冷页面提升。这是为了模拟访问模式周期性变化的场景,工作负载名字里带上「modified」的原因就在这儿。

也就是说,4.43% 是在一个被人为扰动得有利于分层的工作负载上跑出来的值。在没被扰动的原始工作负载上,任何分层实现都没能测出差异。

降级其实一次都没发生。 正如 cover letter 自己交代的,那个用于模拟的扰动从工作负载一开始就在运行,导致 DRAM 层的使用量始终停留在水位线以下,所以所有测试运行里都没有发生真正的降级。这张表比较的不是基于 LRU 的降级和基于 DAMON 的降级,它只包含 NUMAB-2 提升和 DAMON 提升之间的差异。

作者本人写下的局限性说明。 cover letter 里专门有一节「Evaluation Limitations」,写道:从某些角度看,这个改动版的 Taobench 可能把画面扭曲得过头了,用更贴近现实的工作负载或者更公平的微基准来评估会更好。作者对自己数字的诚实程度,很难要求更多了。

还有标准差。 相对分数的标准差在 1.48% 到 3.02% 之间。4.43% 高于这个区间,但也没有高出太多。

真正有意思的其实是另外一行。 在同一个测试里,NUMAB-2 ——也就是内核里已经有的那个现成分层功能——反而把性能拖低了 7.36%。 作者推测,这是因为 NUMAB-2 的同步式提升阻塞了 Taobench 真正的工作进度。前面提到的「在进程自身上下文里做提升」,在这里付出了代价。

把这张表一句话总结就是——在一个被硬生生制造出理由需要分层的工作负载上,新方案赚了 4.43%,旧方案亏了 7.36%。

25% 这个数字 — 以及它其实不是分层

6.17 的多目标迁移身上贴着 25%。原始 cover letter(Bijan Tabatabai,Micron,2025-07-02)同样把条件全写清楚了,而且这个案例和前面那个性质完全不同。

测试环境。 128 核 256 线程的 AMD CPU,本地 DDR 带宽 72 GB/s,CXL 带宽 26 GB/s。工作负载是一个带宽密集型的 embedding reduction 应用,每次迭代复用同一份分配,并报告每次迭代的耗时。

过程。 一开始系统带宽利用率低,所以把交错(interleave)权重设为 1 比 0,全部分配到本地内存。工作负载一启动,本地带宽就饱和了,这时把权重改成 3 比 1,让 DAMON 把数据搬走。迭代时间从 7,600ms 左右降到 5,630ms 左右,cover letter 把这记作大约 25% 的加速。

这里有个关键的转折。 这不是「热的放快层,冷的放慢层」。恰恰相反,是故意把热数据放到较慢的 CXL 上,从而把两层的带宽叠加起来。这是带宽交错(interleaving),不是容量分层。

我自己核对了一下这些数字是否能对得上。72 加 26 是 98,98 除以 72 是 1.361,所以如果这是带宽瓶颈,时间应该变成原来的 0.735 倍。7,620ms 乘以 0.735 约等于 5,600ms,而实测值约为 5,634ms,误差落在 1% 以内。3 比 1 的权重,也贴合带宽比 72 比 26(约 2.8 比 1)。也就是说,这 25% 完全可以用带宽叠加解释,不多也不少。如果不是一个纯粹受带宽制约的工作负载,这个收益是不会出现的。

而最应该诚实的部分。 把权重从 1 比 0 改成 3 比 1 的,是人。 而且恰好就在带宽饱和的那一刻。cover letter 并没有隐瞒这一点——它明确写道,这个补丁集只是新增了一个改变数据如何交错的机制,至于权重该是多少,这个方针留给用户空间。它还提到,正在开发一个用户空间程序,用来监控系统带宽利用率或访问延迟来调整权重,但还没准备好公开。

把这个闭环补上的那一块,就是前面时间线里出现过的 node_eligible_mem_bp。这是一个以 basis point 为单位、衡量匹配某个 scheme 访问模式的内存中有多少比例落在特定节点上的 metric,把它设为目标之后,配额自动调优器就能自己维持类似「60% 的热数据在 DRAM、40% 在 CXL」这样的分布。提交 9138e27a3bc3(Ravi Jonnalagadda,Micron)就是它的实现。

有三点值得留意。第一,这个提交的作者日期是 2026-04-28,提交日期是 2026-05-29。7.1-rc1 发布于 2026-04-26,所以它错过了 7.1——事实上 DAMOS_QUOTA_NODE_ELIGIBLE_MEM_BP 在 v7.0 和 v7.1 里都不存在,它第一次出现是在 v7.2-rc1。 而 v7.2 目前还不是正式发布版(截至撰稿时最新标签是 v7.2-rc3),所以截至今天,还没有任何正式发布的内核带有这个特性。 (LWN 的文章写这个特性合并进了 7.1-rc1,但演讲者本人的幻灯片写的是「7.1-rc1 之后合并进 mm-new」,源码支持的是幻灯片这一边的说法。真正进了 7.1-rc1 的,是配额目标调优算法那部分。)

第二,这个提交里没有任何一个性能数字。 虽然有一节「Testing Results」,但内容只是说在一个双节点异构内存系统上做了功能验证,TEMPORAL 调优器能较快收敛到目标分布、CONSIST 调优器收敛得更慢,到达目标所需的时间会随工作负载强度变化。这是一份收敛行为的报告,不是加速比报告。

第三,它需要 CONFIG_DAMON_PADDR,只能在物理地址空间里工作。相比之下,6.17 的加权交错专属于虚拟地址空间——因为 folio 的目标节点是根据它在 VMA 内被映射的偏移量来决定的,而在物理地址方案里要弄清楚这一点,需要一次代价高昂的 rmap 遍历。也就是说,这套机制和它的自动调优目标,分别活在两个不同的地址空间里。

总结一下:25% 是真的,但它是靠人手动扳动开关得到的值,而能自动扳动这个开关的东西一年后才姗姗来到 -rc 阶段,而且至今还没有性能数字。

94% 这个数字 — 一个没有条件的数字

LSFMM+BPF 2026 上最大的数字是 94%。TPP-DAMON 单线程实在太慢,于是转向了多线程模型,据称在 llama.cpp 基准测试上能带来 94% 的改进。这是 SK hynix 做的工作。

拿到演讲者本人公开的幻灯片原件核对一下,那张幻灯片是这样的——标题「Multi-thread Tiering (SK hynix)」,三条要点:按子区域拆分的 DAMON worker 线程、加速发现热/冷页面、加速迁移。以及最后一条要点「Achieves ~94% llama.cpp speedup」。

就这些。没有说是什么硬件、什么模型、和什么做对比、跑了多少次——什么都没有。我没能找到任何公开的 cover letter 写明这个数字的条件。DAMON 项目自己的新闻列表里也没有这一条。LWN 的文章报道了同样的 94%,但那只是转述同一场演讲,算不上独立确认。

我不是在说这个数字是「假的」。只是值得拿来对比一下。4.43% 身上附带着硬件规格、工作负载参数、5 次重复、标准差那一列,还有作者亲笔写的局限性小节。94% 身上附带着一条要点。在这个领域,数字的大小和方法论的多少,大体上成反比。 而继续往下读幻灯片会发现这样的话——TPP-DAMON 积极的测试结果是「私下分享的」(privately shared),没有进一步的活跃开发计划,已经进入维护(support)模式。

也就是说,内核分层这块招牌式的自动调优模块,在没有任何公开性能依据的情况下转入了维护模式,开发力量转移去了下一个东西——NUMA-TPP-DAMON。用幻灯片自己的话说,那还处于「头脑风暴级别的早期构想」。

真正的问题不在算法,而在参数

为什么这个社区如此执着于自动调优,威斯康星大学研究团队的一篇论文解释得很清楚。From Good to Great: Improving Memory Tiering Performance Through Parameter Tuning(Kanellis 等,arXiv:2504.18714,2025-04-25)的摘要写道——现有的分层方案靠启发式规则和预先设定好的阈值来决定放置和迁移,因此无法适应工作负载和硬件的变化,运行在次优状态。

研究团队用贝叶斯优化搜索了现有分层系统(HeMem 和 SK hynix 的 HMSDK)的参数,报告称如果把值调对,相对同一系统的默认设置能有 2 倍的性能,相对当时最先进的分层系统也能有 1.56 倍。

把这句话和前面的 4.43% 放在一起看,画面就清楚了。换算法能拿到的是个位数百分比,而把同一个算法的参数调对,能拿到 2 倍。在分层这件事上,真正决定收益的不是机制,而是调优。默认设置正在白白丢掉一半的收益。

同时,这也是个坏消息。因为拿到那 2 倍的方法是贝叶斯优化,也就是针对每个工作负载都跑一次昂贵的搜索。在生产环境里,有能力为每个工作负载都跑一遍参数扫描的组织并不多。内核想做的自调优,正是试图用一个在线反馈回路来取代这种搜索,而从 6.16 的利用率/空闲空间目标,到 7.2-rc1 的分布目标,走的就是这条轨迹。只是还没走到终点。

还没解决的事

演讲里提出的那些悬而未决的问题,最准确地说明了这项技术现在的成熟度。

DAMON 不知道是谁访问的。 正如自调优分层的 cover letter 明确写的那样,这套设计只假设了单个 CPU NUMA 节点的情况。作者直接写道,因为 DAMON 无法得知访问信息的来源,把它应用到有多个 CPU NUMA 节点的系统上会变得复杂。考虑到双路服务器有多常见,这不是一个小小的附带说明。

DAMON 和 NUMA balancing 在抢同一个 bit。 因为两者都用 page-idle bit 来检测访问,所以彼此触发的缺页中断,会被对方当成自己「测到」的结果。演讲里提出的候选方案是:编译期互斥(内核里只放二者之一)、运行期隔离(同一时间只激活一个)、部分隔离,或者干脆放任它们互相干扰。Park 的提议是,等必要的清理工作完成之后,第一版实现要么用编译期互斥,要么干脆先忽略这个问题。走互斥这条路,发行版就会陷入必须二选一的尴尬处境。会议上 Davidlohr Bueso 对多个层为了内存放置决策互相打架这个问题的担忧,也是同一脉络下的事。

下一代还只是个想法。 NUMA-TPP-DAMON ——把分层泛化为 NUMA 放置的一个特例,给 CPU、GPU 等每个访问者(accessor)各自跑一条独立提升路径的构想——目前还处在头脑风暴阶段,前面还横着一个按访问者分别监控这个难题。

还有文档。 node_eligible_mem_bp 已经出现在 v7.2-rc3 的 include/linux/damon.h 里,但还没进入 DAMON 设计文档的配额目标 metric 列表。文档滞后是常有的事,但这也说明了这个特性有多新。

那么,你现在该不该开启它

值得开启的情况

  • 服务器不是被核心数卡住,而是被内存容量卡住,而且工作负载内存中有相当一部分确实是冷的。(Meta 在 Vistara 论文里报告的、处于这种状态的 fleet 占比是 43.7%。)
  • 工作负载受带宽制约,而且把 CXL 带宽叠加起来确实有得赚。这种情况下要看的是加权交错,而不是容量分层——把上面 25% 那个案例的算术,拿你自己硬件的数字重新算一遍,上限立刻就出来了。
  • 有余力针对真实工作负载去调参数。按上面那篇论文的说法,2 倍的收益就藏在这里。
  • 只有一个 CPU NUMA 节点。

还不是时候的情况

  • 访问模式是静态的。4.43% 那个实验里未经改动的原始 Taobench 就是这样,结果是不管哪种实现都测不出有意义的差异。分层只有在冷热随时间变化时才值钱。不变化就没有搬动的理由。
  • 期待的是「装上就自动能用」。mainline 里没有分层模块,damo 命令行加上几个手工挑出来的常数,都得你自己来。
  • 双路及以上。这套设计目前还没假设这种情况。
  • 跑的是延迟敏感型服务,而且余量本来就紧。降级一旦判断错误,那个页面下一次被访问时,就得原样承受 CXL 的延迟。
  • 以为开了 NUMAB-2 就万事大吉。上面那张表里,那是 7.36% 的损失——至少在那个工作负载上是这样。

不管做什么,顺序只有一个——先测量你工作负载的访问模式。好在这件事现在已经很容易了。DAMON_STAT 在 6.17 合并进来,而且在 Debian 的内核里是默认构建启用的。在不知道有百分之多少的页面已经多少个小时没被读过的情况下就开启分层,正如上面这个实验精确展示的那样,就是在为一件毫无意义的事付出迁移开销。

结语

总结一下。Linux mainline 从 2024 年的 6.11 一路到 2026 年的 7.2-rc1,持续稳定地接收着 CXL 分层的各个零件,而这些零件大多是卖内存的公司(SK hynix、Micron)和资金被内存绑住的公司(Meta)亲自写的代码。这些零件本身设计得不错。

但说句实话,今天的 mainline 里,没有装上就能用的分层模块,CONFIG_DAMON 默认是关闭的,自动调优的最后一块拼图还没进入正式发布版,而那个招牌模块在没有公开性能依据的情况下转入了维护模式。在被引用的这些数字里,文档最完善的是 4.43%,而它也是靠人为扰动工作负载才测出来的;最大的那个数字 94%,则完全没有附带任何条件。

CXL 被过度炒作这种说法很常见。但从内核这一侧看到的画面稍有不同——这里的进展缓慢,却是真实的,而且最重要的是,做这些工作的人,对自己的数字异常诚实。 他们会在 cover letter 里写「这个工作负载可能把画面扭曲得过头了」,会在幻灯片上写「结果是私下分享的」。夸大其词大多不是出自写这些代码的人,而是出自那些把它转述、传播出去的层级。

所以,如果你在评估 CXL 分层,不要看厂商材料,去读 cover letter。里面早就写好了数字,以及这个数字没有测到的那份清单。

参考资料

현재 단락 (1/107)

CXL 硬件的故事,我们已经在[让退役的 DDR4 重获新生 — Meta 的 CXL 桥接芯片 Vistara](/blog/2026-07-11-meta-cxl-ram-reuse)那篇里讲过一...

작성 글자: 0원문 글자: 10,679작성 단락: 0/107