H40

CXL 与内存池化

点击正文段落选定收藏或划线位置;未选定时使用屏幕内第一段。

课内目录

1 CXL 与内存池化要回答什么

设想机房里有 8 台双路服务器,每台安装 512 GiB DRAM。有的服务器常年只用到 280 GiB,有的任务却在申请到 480 GiB 后开始频繁回收页面。空闲容量就在隔壁机器上,但软件不能因为机柜里还有内存,就把它当成当前 CPU 的普通内存条使用。传统扩容通常需要停机、检查插槽与通道配置、插入合适的 DIMM;整机采购时预留过多容量,又可能让大量 DRAM 长期闲置。CXL 与内存池化要回答的核心问题,是能否让容量的安装位置与使用位置不再紧密绑定。

CXL 是 Compute Express Link 的缩写,是连接主机处理器与设备的互联标准。它利用 PCIe 的物理基础,在支持的处理器端口、主板布线和设备之间提供额外的协议能力。外形像 PCIe 扩展卡,不代表设备一定支持 CXL;插槽能插进去,也不代表 CPU 根端口、固件和操作系统能够把其中的内存加入系统。判断兼容性,要看整条路径,而不是只看连接器照片或“支持高速接口”的说明。

最直观的起点是内存扩展:服务器本地 DIMM 提供 512 GiB,再接入带有 256 GiB DRAM 的 CXL 内存设备。系统经过发现、配置与上线过程后,可以获得额外的可寻址容量。但这 256 GiB 经过的控制器与链路更多,其性能不能由“都是 DRAM 颗粒”直接推断。CPU 插槽旁的 DIMM、机箱里的扩展卡、经交换设备连接的内存盒,属于不同的访问位置,也可能对应不同的延迟、带宽与故障范围。

池化在扩展之上增加容量分配能力。例如,1 个内存池有 1 TiB 容量,可以按平台支持的粒度划分给不同主机。上午为批处理服务器配置 512 GiB,任务结束并完成安全回收后,再把其中的容量配置给其他服务器。这里的“分给”首先是资源管理动作,不是每次 CPU 读取都向全机柜广播寻找空闲页面。池的分配单位、调整方式、是否需要重启,都必须由具体硬件与软件实现说明。

还要区分池化与共享。池化可以让不同主机在不同时间或不同分区上使用同一个物理内存池,却不自动允许它们同时读写同一段地址。跨主机共享需要明确的标准版本、设备能力、软件支持与同步机制。入门阶段先建立更实用的目标:让不同性能的内存容量被正确发现、分配和使用,同时保证故障可定位。不能把“容量可调”简化成“任意服务器随时共享全部内存”。

本地内存、CXL 扩展与池化的关系
本地内存、CXL 扩展与池化的关系

2 一致性内存与设备类型

普通程序通过地址读写数据,CPU 通常先访问缓存,再在需要时向内存系统取回数据。所谓一致性,关注的是参与者缓存中的副本如何保持符合规则的可见关系。设备接入一致性体系,可以减少某些场景中由软件显式搬运与维护副本的负担,但一致性不是“同时发生”,也不等于每次访问都很快。程序中的锁、原子操作以及并发访问规则依然有自己的责任,不能靠接口名称代替。

CXL 体系中常见的协议名称包括 CXL.io、CXL.cache 和 CXL.mem。CXL.io 负责设备发现、配置等基础交互;CXL.cache 允许具备相关能力的设备一致性地访问主机内存;CXL.mem 让主机通过内存语义访问设备侧内存。这里的内存语义可以理解为,处理器针对已映射的地址发出读写,而不是把每次读取组织成磁盘文件请求。具体设备实现哪些协议,决定了它适合承担哪类角色。

常用的设备分类有 Type 1、Type 2、Type 3。Type 1 具备一致性访问主机内存的能力,但没有通过 CXL.mem 向主机提供的设备内存;Type 2 同时具有设备侧内存与计算能力,可涉及主机和设备之间的数据访问;Type 3 主要提供内存扩展能力,是本课讨论容量池化时的主要对象。分类描述的是协议能力组合,不是卡的长度、内存颗粒品牌或标称容量,也不能直接当成性能排名。

把 Type 3 设备画在服务器里,可以看到 3 个层次:DRAM 颗粒保存数据,设备控制器负责介质与访问处理,CXL 链路把设备连到主机。CPU 能使用这些容量,还需要平台把相应地址范围建立起来。操作系统可能把它作为普通系统内存管理,也可能通过设备接口供软件显式映射;这些使用方式受到系统版本和配置影响。设备已经枚举出来,与应用已经能分配到它,是不同的检查点。

PCIe 网卡与 NVMe SSD 可以帮助理解边界。网卡把网络报文送入或取出主机内存,SSD 通常通过块设备接口提供持久存储;即使它们也位于 PCIe 插槽,也不能因此被视为 CXL 内存。相反,装有易失性 DRAM 的 CXL 内存设备虽然看起来像扩展卡,主要用途仍可能是扩展运行内存。它断电后是否保留数据,要看实际介质与平台承诺,不能从 CXL 这个名称得出持久化结论。

因此,讨论“一致性内存”时需要连着说清参与者、地址范围和能力边界。本课关注主机怎样访问分配给自己的设备内存,不展开缓存状态机、协议报文格式和跨主机一致性细节。只要记住:一致性解决数据副本的规则,地址映射解决访问落点,容量管理解决谁能使用多少;它们相互配合,却不能互相替代。

3 延迟、带宽与池化边界

延迟回答“这次读取多久回来”,带宽回答“单位时间能搬多少数据”。2 者经常同时影响表现,但不能混为一谈。顺序扫描 100 GiB 数组时,程序可能发出很多并行请求,更容易碰到链路或介质带宽上限;沿着指针追踪数据结构时,下一次地址依赖上一次结果,即使链路还很空,也可能主要受单次访问延迟限制。相同容量的设备,在这 2 类负载中的收益可能完全不同。

以 PCIe 5.0 物理基础上的 x8 链路为例,32 GT/s 是每条通道的传输速率,不能直接读成 32 GB/s 的应用带宽。考虑线路编码后,x8 单向数据速率的理论量级约为 31.5 GB/s;协议开销、请求类型和实现限制还会压低可用值。链路全双工也不代表单向读取能把双向数字相加。主板若把同一组通道切给其他设备,或者设备实际只协商到更窄链路,性能预算还需要重新计算。

访问延迟同样不能用某个标准版本对应的固定数字表达。CPU 型号、端口实现、设备控制器、介质、交换跳数与负载都会改变结果。为了讨论,可以假设某台测试机的本地内存相关读取延迟为 100 ns,扩展内存为 250 ns;这只是后文的教学参数,不是对所有 CXL 平台的保证。采购或上线前必须以目标机器、目标访问方式的实测值替换它们。

池化还会引入共享边界。2 台主机各获得 256 GiB,并不表示各自都拥有独立的全部后端带宽。它们可能共享交换上联、设备控制器或 DRAM 通道。容量分配正确时,仍可能出现争用;单机空载测试足够快,也不能证明多机同时扫描时足够快。评估时要把主机端口、交换路径、设备端口和介质带宽画在同一条链上,找出最窄的部分。

更远也需要准确描述。本文“远内存”指相对当前 CPU 更远的内存层,可能位于同机箱的 CXL 设备或经交换连接的内存盒,并不默认经过以太网或跨机房。距离首先体现为访问路径和共享资源,不能只用机箱之间的厘米数估算。双路服务器还存在本地与另一 CPU 插槽内存的 NUMA 差别,比较 CXL 前应先固定线程与分配位置,否则容易把跨插槽代价混进结果。

由此可以划出池化边界:容量不足、访问较冷或可并行的数据,可能适合较远内存;高频访问、强依赖链和严格尾延迟路径,需要优先保护本地资源。这里的“可能”要由负载验证。若扩容避免了频繁访问 SSD 交换空间,即使远内存慢于本地 DRAM,也可能显著改善整体表现;若工作集原本完全装得进本地内存,迁出热点则可能只有代价。

容量、访问比例与观测指标之间的关系
容量、访问比例与观测指标之间的关系

4 动手:画一条 CXL 访问路径

拿出纸,把测试平台限定为 1 台双路服务器、每个 CPU 插槽各有 256 GiB 本地 DRAM,再给 CPU 0 所属的端口接入 1 个 256 GiB Type 3 内存设备。先画 CPU 0、CPU 1、本地 DIMM、端口与设备控制器,标出设备属于哪个处理器的连接路径。如果还有交换设备,就在端口与内存设备之间补上它。此时不要急着写“总内存 768 GiB”,先确认这部分容量能否被当前系统上线使用。

接着画应用线程、虚拟地址与物理地址范围。应用看到的是自己的虚拟地址,系统通过页表建立到物理页面的映射;平台再根据配置把物理地址访问送往相应内存目标。某些配置还可能在多个目标之间交织地址,因此“一个 NUMA 节点必然等于一张卡”并不可靠。本练习先采用不交织的简化配置,让一段物理范围对应 CXL 内存,方便看清落点。

现在假设线程运行在 CPU 0,所需数据不在缓存中,目标页面位于 CXL 内存。用箭头依次连接 CPU 的内存访问路径、CXL 根端口、可选交换设备、设备控制器与 DRAM,再画返回数据的箭头。CPU 发出的实际访问通常围绕缓存行等传输单位组织,而应用可能只是读取其中的 8 字节变量。地址映射通常已由平台预先建立,不能把管理软件画成每次读取都必须经过的中转站。

把同一个线程移到 CPU 1,重新描线。若设备仍接在 CPU 0 一侧,访问可能多经过处理器之间的互联。再把目标页面改成本地 DIMM,比较路径的长度和共享点。这个练习不要求推导纳秒数,而是要求能解释:线程位置、页面位置和物理连线中的任意一项改变,都可能改变测试结果。只记录“用了 CXL”不足以让别人复现。

在实际 Linux 平台上,可以用 lspci 辅助检查设备与链路,用 numactl --hardware 查看系统暴露的 NUMA 信息;支持相应工具的系统还可用 cxl list 查看 CXL 拓扑和内存区域。命令可用性与输出字段取决于发行版、内核和工具版本。这些信息应与固件设置、内存上线状态交叉核对,不能用“出现一个设备名称”替代容量与访问路径验证。

最后给图加上失败标记:链路降速标在端口旁,容量未上线标在系统内存视图旁,远端页面误分配标在线程到页面的箭头上。这样得到的图既能解释正常访问,也能指导排查。课堂产物应包含连接宽度、协商速率、容量归属、线程位置和页面落点;无需记录高级协议细节,就能把“慢在哪里”从抽象抱怨变成可检查的问题。

从应用地址到 CXL 设备 DRAM 的访问路径
从应用地址到 CXL 设备 DRAM 的访问路径

5 容量弹性与时延取舍

容量弹性的价值,需要和业务工作集一起衡量。假设某分析任务有 700 GiB 活跃数据,而服务器只有 512 GiB 本地内存,额外 256 GiB 扩展内存可以让更多页面留在内存层级,减少昂贵的存储访问。但如果任务的真正热点只有 120 GiB,则合理目标应是把这部分留在本地,让较冷数据使用扩展容量。按数据总量平均摆放,看似简单,可能让最重要的页面承受额外代价。

先做一个有限用途的估算。设真正到达内存层的访问中,远内存比例为 p,本地访问延迟为 L,远内存延迟为 R,暂不考虑排队与并行,可写成平均值 (1-p)×L+p×R。取 L=100 ns、R=250 ns,p=20% 时结果为 130 ns,p=60% 时为 190 ns。这能直观展示访问比例的影响,但不能拿来直接预测应用每秒请求数或 p99 延迟。

容量比例与访问比例不相等。把 50% 页面放在远内存,若这些页面很冷,远访问比例可能只有 5%;反过来,远端仅占 10% 容量,却存放高频索引,可能承担大部分访问。平台方案需要同时记录“放了多少”与“访问了多少”。不能因为扩展容量占比低,就默认对关键路径影响很小,也不能因为远端容量占比高,就判断一定不可用。

动态调整也有成本。将页面迁回本地需要复制数据、更新映射并消耗带宽;持续来回移动的页面可能让系统更忙。容量从某台主机撤回时,还必须处理该区域上的在用页面,确保数据与引用都完成迁移或释放。若本地和其他层没有足够空间,回收可能失败或耗时很长。管理界面上的容量滑块,并不代表真实硬件能无成本地即时改变应用可用内存。

制定策略时,可以把本地内存预算留给关键线程的活跃数据,把可容忍延迟的缓存、批处理数据或冷页面作为扩展层候选。自动分层可以减少人工维护,但仍要观察热点识别是否及时、迁移是否过多、多个应用是否争抢本地容量。显式分配让软件更清楚数据位置,却增加改造成本。两种方式都要围绕目标应用选择,不能仅凭“自动”或“透明”下结论。

还有一个容易漏掉的成本是故障影响。独立 DIMM、单张扩展卡和共享内存盒覆盖的应用范围不同。池化提高容量利用率时,可能把更多主机的容量依赖集中到同一个设备或交换路径。是否存在冗余、失效时怎样处理、重建需要多久,都应进入容量收益的讨论。内存里的副本只有在故障后仍可访问且软件能够使用时,才构成有效的恢复能力。

6 常见坑:把池化内存当本地 DRAM

最常见的错误,是扩容后只看系统显示的总容量。原先 512 GiB 变成 768 GiB,应用分配成功,于是宣布升级完成。实际上,关键数据可能进入远内存,应用延迟已经恶化,只是还没有触发内存不足报警。验收必须同时覆盖可用容量、数据落点与服务表现。容量是资源指标,业务请求是否按时完成才是结果指标。

另一个错误是只测顺序带宽。连续读取大数组可能把链路利用得很好,但查询索引、图遍历或对象引用链可能只有较低的访问并行度。带宽测试正常而业务变慢,并不矛盾。测试组合应至少包含与实际负载接近的访问方式,并记录线程数量、工作集大小、读写比例和放置方式。随机访问结果也不能孤立解释,因为缓存命中率与并发程度会改变瓶颈。

第 3 类错误来自接口和主板。某个机械 x16 插槽可能只连接 x8 通道,也可能在插入另一张卡后改变通道分配;设备经过转接板、背板或线缆时,还需要满足平台支持条件。普通 PCIe 交换器不能凭借外形相同就被当成支持相应 CXL 能力的交换设备。固件设置不匹配、链路训练异常或散热不足,都可能导致设备无法使用、链路降速或性能波动。

第 4 类错误是把“支持热插拔”理解成“可以随手拔出”。内存设备承载的是正在被 CPU 使用的数据与地址范围,移除前必须经过受支持的撤回流程。即使平台允许在线增加容量,也不代表所有在用内存都能在线移走。突然丢失设备或链路,可能造成访问错误、进程终止,甚至系统故障,具体影响取决于平台错误处理能力。维护流程必须按内存依赖设计。

第 5 类错误是把可纠错当成不会失败。ECC 可以处理特定范围的介质错误,却不能保证覆盖控制器失效、链路中断、供电故障或所有不可纠正错误。运维应能区分介质告警、链路错误和软件分配问题,并明确告警归属。观察到错误计数上升时,需要结合设备位置、发生时间和受影响地址范围判断,不能仅通过重启清空现象。

最后要防止把容量池视为天然隔离的公共空间。容量从主机 A 释放后分给主机 B,平台应按约定清理数据并建立正确的访问边界;旧映射与残留内容都不能被忽视。这里只需把它作为采购与验收问题记录下来,不展开底层安全协议。可迁移的原则是:硬件共享之后,分配、回收、隔离与恢复都需要明确的责任方和可验证行为。

7 案例:远内存延迟打爆尾延迟

某台服务器运行内存索引服务,本地 DRAM 为 512 GiB。团队接入 256 GiB CXL 扩展内存,希望容纳增长的数据。下面使用一组教学观测值:升级前 p50 请求延迟为 2 ms,p99 为 8 ms;升级后 p50 为 2.3 ms,p99 升到 25 ms。CPU 总利用率没有明显上升,系统仍有空闲内存,顺序带宽测试也通过。若只看平均值与总容量,这次退化很容易被漏掉。

排查先固定请求集、线程数量和线程绑定位置,保留升级前的放置策略作为对照。随后查看页面分布,发现新增容量上线后,分配策略让部分热点索引进入远内存。该服务的查询需要沿着多个节点读取,每次访问的地址依赖上次返回值,无法充分并行。这里的“多个”不是指整个查询只读几个缓存行,而是关键依赖链反复累积等待,热点落点因此格外重要。

延迟为何主要表现在尾部?部分请求恰好需要更多远端节点;高峰时这些请求占用执行资源更久,后续请求开始排队。共享链路或设备控制器的争用还可能继续放大等待。因此,单次内存延迟从 100 ns 变到 250 ns,并不意味着每个请求都固定慢 2.5 倍,更不能把额外的 150 ns 直接当成 p99 的增量。需要同时检查访问结构、并发负载和排队。

团队进行受控对比:先把热点索引放回本地层,较冷的数据继续保留在扩展层,维持相同请求压力;再逐步增加并发,观察尾延迟何时陡升。同时检查协商链路宽度、错误计数和设备状态,排除降速或硬件错误。若热点回迁后 p99 明显恢复,而硬件状态稳定,就有了支持“放置策略导致退化”的证据,而不是仅凭时间上的先后归因。

回迁本身也应被观察。迁移期间出现短暂带宽高峰,不应和稳定运行状态混在一起比较;若系统不断把同一组页面迁出又迁回,则需要调整策略或预留本地容量。最终验收应包含冷启动、稳定运行和负载高峰,分别记录关键指标。只给出一次短测试的最佳值,无法说明长期运行的表现。

这个案例的处理目标,是在容量增长的同时守住尾延迟约束。可以限制关键服务使用的远内存比例,也可以保留足够的本地空间,或让适合扩展层的批处理任务使用新增容量。若硬件确实存在错误,则应转入设备维护流程;若瓶颈来自正常路径代价,则需要调整数据放置和资源预算。不同证据对应不同动作,避免把所有退化都归结为“CXL 慢”。

从尾延迟异常到放置策略和硬件路径的排查
从尾延迟异常到放置策略和硬件路径的排查

8 把内存分层写进平台方案

平台方案应先定义目标,而不是先决定购买多少扩展卡。例如,目标可以是让 700 GiB 的分析工作集保持在内存层,或把现有服务器的空闲容量利用起来,同时满足关键服务 p99 不超过 10 ms。前者偏重容量与吞吐,后者需要容量管理和隔离策略。目标不同,机器形态、设备连接和验收负载也会不同,不应共享同一份简单的“每 GiB 成本”结论。

硬件清单要能还原实际访问路径:CPU 插槽数及端口归属、本地 DIMM 容量与通道配置、CXL 设备类型、链路代际与宽度、交换路径、设备介质容量,以及必要的供电和散热条件。软件清单则记录固件、操作系统、驱动与管理工具的受支持组合。这样更换主板或升级内核时,团队才知道哪些结论需要重新验证,而不是依赖一张泛泛的兼容性标签。

容量策略应说明哪些数据有资格进入扩展层,谁负责决定页面位置,本地空间不足时怎样处理。池化策略还需说明容量的初始分配、调整粒度、回收前提和失败处理。若需要停机或重启才能完成某项调整,应把维护窗口写进流程。若系统支持在线操作,也应规定超时与失败后的处理,不能把所有变化都承诺为无感完成。

验收建议使用 3 类证据:硬件路径确实符合配置,页面实际落在预期位置,目标应用在规定负载下达到要求。容量与带宽的独立测量帮助解释结果,应用 p99、吞吐和错误率决定能否上线。涉及池化时,应增加多主机同时使用的测试;涉及分层时,应覆盖热点变化。测试条件和结果必须成对保留,否则一次调优成功很难变成可重复的平台能力。

最后写清回退路径。若尾延迟越界,可以暂停新增容量分配、调整放置策略,或在确认剩余空间足够后撤回相关内存区域;具体动作取决于平台支持。不能在本地容量装不下工作集时承诺直接关闭扩展层。回退方案应有执行条件和责任人,并说明数据如何保留、服务是否需要降载或重启,让扩容收益与运行责任同时落地。

9 从CXL 与内存池化走向高速互联(H41)

学习 CXL 后,再看网卡、存储和处理器互联,会发现共同的问题:数据要经过哪些端点,使用什么协议,谁提供带宽,哪里产生排队,故障又影响哪些消费者。接口速率只是其中的一个数字。即使设备标称速率更高,若 CPU 通道分配不足、上联共享严重或软件请求并行度不够,应用也未必得到预期收益。

同时要保留语义差别。CXL 内存访问、NVMe 块请求和以太网报文不能只按 GB/s 直接替换;它们让软件面对的操作方式、等待路径与错误处理不同。向远内存读取地址,与向存储设备读取一个块,可能最终都在搬运字节,却对应不同的管理边界。H41 将在这个基础上讨论高速互联的链路、拓扑和系统瓶颈,本课不提前展开报文编码或高级交换内部机制。

进入下一课前,应能用自己的路径图说明 4 件事:新增容量装在哪里,CPU 怎样访问它,哪些资源被共享,关键负载如何证明收益。若只能回答“设备用了更新的接口”,说明分析还停留在标签层面。把内存层级、软件放置和物理连线放在同一张图上,才有条件进一步比较不同高速互联怎样服务真实服务器。

放进方案里

本平台以 512 GiB 本地 DRAM 作为关键工作集的优先层,接入 256 GiB Type 3 CXL 内存作为容量扩展层。目标是承载约 700 GiB 的分析数据,并使关键查询在规定并发下保持 p99 不超过 10 ms。上述容量为方案起点,实施前须根据工作集、可用空间及系统预留量复核,不能把设备标称容量全部当成应用可用容量。

设备连接到指定 CPU 所属端口,记录实际协商的链路速率与宽度。采用经过验证的处理器、主板、固件和操作系统组合;确认内存区域已正确配置、上线,并能观察页面位置。关键索引优先留在本地层,较冷数据进入扩展层,禁止仅按容量比例推定访问比例。自动迁移策略需要记录迁移量与稳定状态,避免热点反复移动。

验收同时覆盖单机稳定负载、负载高峰和热点变化,记录吞吐、p50、p99、页面分布、链路状态及错误计数。若采用共享内存池,增加多主机争用测试,并明确每台主机的容量配额、共享带宽边界和故障影响范围。测试使用实际查询访问方式,顺序带宽结果只作为辅助证据。

池化回收验收应包含页面无法迁移的场景:撤回失败时,原主机仍保有该地址范围的有效访问权,管理端不得将其重复分配。保留区域归属、撤回状态与页面迁移结果作为证据;只有确认撤回完成并清理数据后,才允许另一台主机接收容量。

容量调整按平台支持流程执行,撤回前确认页面能够迁移或释放,并预留接收空间与维护时间。设备离线、链路失效及不可纠正错误分别制定恢复动作;未验证恢复能力前,不承诺在线无损切换。容量重新分配时验证访问隔离和数据清理。若关键延迟越界,先降载并恢复已验证的放置策略,再依据容量条件决定是否撤回扩展层;回退条件、执行人和业务恢复检查均纳入运行手册。

10 小结:下一步高速互联(H41)

CXL 让受支持的主机能够以内存语义访问设备内存,池化进一步提供容量分配能力。收益取决于容量压力、访问位置、链路资源和软件放置;一致性不会消除距离,容量增加也不会自动改善尾延迟。

继续学习 H41 时,带上这条分析顺序:先辨认访问语义,再画端到端路径,随后检查带宽、延迟、共享点和故障边界。任何高速接口都要回到目标负载,才能判断它是否真正解决了平台的问题。

同阶段相关课

AI 答疑

默认关闭。启用后,只发送本课标题、最近阅读的屏幕内正文摘录(最多 6000 字)与本次问题。

配置自己的服务