最近帮一个客户评估大模型推理扩容,方案评审会上有人说“直接加四张A100”,我听完摇头。不是因为加卡不对,而是因为真正卡住的根本不是算力,而是显存和内存带宽。当时那张卡上住了70B的权重,KV Cache再塞几千个并发请求就要爆了。后来我们把KV Cache挪到内存池里,QPS反而从几百涨到一千多,加的卡一张都没买。
这个案例背后就是标题里那三个词的真实含义:AI芯片不是只会堆算力,内存瓶颈才是当前压倒骆驼的最后一根稻草;而“解耦内存”正是行业为了绕开这堵墙正在悄悄做的事情。这篇文章,我想从一个做AI基础设施的人视角,把“内存瓶颈到底卡在哪”“解耦内存方案到底长什么样”“落地会踩哪些坑”“什么时候该上”这几件事讲透。适合正在做大模型训练、推理服务、异构计算集群的算法和基建同学参考。
1. AI芯片的“内存墙”,到底卡在哪几个具体数字上
1.1 算力翻倍、带宽只涨一半,墙就是这样砌起来的
先看一组很直观的对比。以几代主流GPU为例,把算力、带宽、容量放在一张表里:
| 型号 | FP16算力(dense) | HBM带宽 | 显存容量 | 大致发布时间 |
|---|---|---|---|---|
| A100 80GB | 312 TFLOPS | 2.0 TB/s | 80 GB | 2020 |
| H100 SXM | 989 TFLOPS | 3.35 TB/s | 80 GB | 2022 |
| H200 | 989 TFLOPS | 4.8 TB/s | 141 GB | 2023 |
| B200 | 约2.2 PFLOPS | 约8 TB/s | 约192 GB | 2024 |
三代产品里,FP16算力大概翻了7倍,带宽只翻了4倍,容量翻了2.4倍。更扎心的是,训练大模型时模型规模本身几年翻几十倍。分母是模型和数据,分子是算力,而中间那根“从DRAM到计算单元”的管子,扩得最慢,它就是内存墙。
为什么说“墙”?因为GPU内部是一个超级能吃吞吐的机器。一个 FP16 矩阵运算单元,每秒钟要吞进去的字节数非常恐怖。按 roofline 模型看,一个算力 989 TFLOPS 的 H100,如果执行的是线性算子,且算力强度在 1 FLOP/Byte 以下,它实际能跑出来的性能根本不是 989 TFLOPS,而是被带宽死死按住。你可以理解成:你请来了一个每秒能做一千个俯卧撑的壮汉,但他每做一次都得先跑半分钟去仓库拿一口吃的。仓库的传送带速度没跟上,壮汉就只能干等。
1.2 HBM再快,堆容量也是按“金库标准”堆的
经常有人问:“既然显存不够,为什么不能把GPU的显存做更大?”答案是能,但代价极大。
HBM是靠硅通孔(TSV)把DRAM die垂直堆叠起来的,本来就小批量、高良率需求。堆叠层数每加一层,良率和散热都指数级变差。再往上堆,要么成本爆炸,要么封装直接放不下。所以你会发现,从H100到H200,NVIDIA愿意把容量从80GB提到141GB、带宽从3.35TB/s提到4.8TB/s,但价格也涨了一大截。这类容量提升本质上是在“金库里再插一排保险柜”,而不是把金库做大到能辐射整座城市。
那有没有便宜的大容量内存呢?有,就是主机侧那条标准的DDR内存通道。它的容量可以做到单机几百GB甚至几TB,可它的带宽只有几十GB/s到一两百GB/s,和HBM差了一个数量级。于是AI芯片面临一个尴尬处境:身边全是又快又贵的顶级食材(HBM),但厨房太小;远处有个大仓库(DDR),运过来却要跨一座窄桥(PCIe总线)。
1.3 训练和推理时,内存到底是被谁吃掉的
先把被吃掉的内存拆清楚,后面讲解耦才有依据。
训练侧,吃内存的主力部队通常是四路大军:
- 参数权重:70B模型用BF16表示,光权重就要140GB左右;
- 优化器状态:用了Adam优化器,每个参数至少两到三个额外状态,算下来比权重还大一截;
- 梯度:每步反向传播都要存;
- 激活值:前向计算时每层中间结果,靠重计算方法可以腾挪,但计算量和显存会互相打架。
推理侧,情况稍微不一样,但KV Cache会是比权重更凶的内存吞金兽。KV Cache是给每个请求单独分配的,一个长上下文请求会把几十GB直接划走。请求并发一上来,再大的显存也会被瓜分干净。
这也是为什么行业里会说“加卡往往治标不治本”——算力还有余量,但每个计算单元的显存被数据塞满了,卡加得再多,每张卡也会因为拿不到数据而空转。真正需要的是在不疯狂加卡的前提下,让芯片能“摸到”更大的内存空间,这就是解耦内存出现的背景。
2. 解耦内存到底干了啥:把“随身背包”改成“共享大行李箱”
2.1 表象是一根线,实质是对资源使用方式的翻新
所谓“解耦内存”,直白地说就是把内存从计算节点的“肚子里面”拿出来,集中成一个或几个独立的内存资源池,让多台计算设备通过网络和专用协议按需访问。以前每台服务器上有多少内存,装完CPU就锁死了;解耦之后,内存像云硬盘一样,哪个节点需要就动态划给哪个,用完释放。
这个概念在数据中心里并不新鲜,早期HPC领域的“内存聚合”、内存型数据库里的RDMA共享内存,本质上都是这个思路。但过去的方案有个共同硬伤:远程内存访问要走网络协议栈,延迟高、开销大,而且软件要显式管理,和本地内存“吃住一体”的体验差太远。直到CXL和高速NVLink这些互连技术出现,远程内存才越来越接近“看起来像本地内存”。
我们可以用一个生活类比来理解:传统方案是你的CPU/GPU手里拿着一个小背包,包里塞不下就走几步去墙角的柜子里拿;解耦内存是直接在街道对面建一个公共大仓库,你家和仓库之间修了一条传送带。传送带快不快、怎么样防止别人拿错箱子,就成了新技术要解决的问题。
2.2 CXL是那根最关键的“传送带”
CXL(Compute Express Link)是当前最受关注的解耦内存技术载体。它基于PCIe物理层,专门为高效共享内存而设计。在CXL的词汇表里,你经常会看到Type 1、Type 2、Type 3设备:
- Type 1:主要用于缓存一致性加速,比如智能网卡;
- Type 2:带计算能力又带内存加速,典型就是带SM的GPU或DPU,它能主动访问主机内存;
- Type 3:最常见的内存扩展设备,本质是一块“内存板”,插到PCIe槽位上,主机可以把上面的DRAM当作自己的内存用。
CXL 1.x/2.0解决的是“把内存扩展卡挂到单台主机上”。CXL 3.0和3.1又把格局放大了:它支持内存池化(Memory Pooling)和内存交换(Memory Switching)。多个CPU/GPU可以连接到一个CXL交换机上,交换机后面挂着几十TB甚至几百TB的内存池,每个主机按需申请逻辑内存。这就让“内存像云资源一样分发”成为现实。
不过我对很多工程的“漂亮架构图”一向不是全信。CXL最值钱的地方在于它在硬件层面提供了一种缓存一致性的内存语义。对比RDMA,用RDMA访问远端内存时,软件需要自己处理网络报文、同步、重传,本质上是在做“用网络协议模拟内存”。CXL则让主机CPU用Load/Store指令就能访问远端内存,硬件保证cache line粒度的一致性,软件几乎无感。这不是一句轻飘飘的“类似”,而是把内存从“需要特别关照的远程资源”降维成了“一种更远但更大、统一寻址的内存”。
2.3 GPU那一侧也有自己的“解耦叙事”
聊AI芯片的解耦内存,不能只看CPU和CXL。NVIDIA这几代产品内部,其实一直在做另一种形态的解耦:把多张GPU卡的显存通过NVLink/NVSwitch逻辑上“合并”成一个巨大的统一显存空间。
最典型的例子就是GB200 NVL72这类超大节点,72块GPU通过NVLink连在一起,每块GPU都能访问整个池子的显存,程序写起来像是握着一张容量巨大的显存盘。这个做法从结果上看和CXL内存池很像,但它的基础带宽高得吓人,NVLink双向带宽能到1.8TB/s甚至更高,所以它可以把“远程显存”当“近似本地显存”来用。而那种跨服务器的内存池,由于受制于PCIe或以太网/IB,带宽低一到两个量级,只适合放冷数据。
所以我的判断是:AI场景里的“解耦内存”有两条腿在走。一条是CXL或者类CXL技术,主攻数据中心里大容量、低成本的冷内存;另一条是NVLink域内的高带宽显存共享,主攻高性能计算池里的热数据。它们解决的都是同一个问题,只是带宽预算不同,直接决定了它们各自适合的放置内容。
3. 落地时最容易被低估的三个工程细节:延迟、一致性、数据放哪儿
3.1 延迟账:远端不是“可以忽略”,而是“必须算进去”
行业里讲解耦内存,都喜欢说“远一点没关系”,但这句话很容易误导人。解耦内存的一切收益都必须建立在“延迟预算充足”的前提下。
看一组典型量级的数字:
| 访问类型 | 典型延迟 | 带宽量级 |
|---|---|---|
| HBM/板载显存 | 100~300ns | TB/s级 |
| 本地DDR内存 | 80~120ns | 50~200GB/s |
| CXL内存扩展卡 | 180~300ns | 30~70GB/s |
| 跨机CXL内存池(经过交换机) | 1~3us | 30~60GB/s |
| NVLink远端显存 | 1~2us | 数百GB/s~1.8TB/s |
对于一般的权重读取,如果你把权重放到了跨机内存池,那每次前向计算都要多等1微秒以上。这个延迟在小batch推理时可能是致命的。所以工程上,我最常给团队的建议是先分清“每次计算必须读的高频热数据”和“偶尔读取或写一次的冷数据”。热数据永远留在HBM/本地显存,冷数据才考虑挪到内存池。
我实测下来的经验是,KV Cache这种数据结构很适合当第一波“试验对象”:推理时KV Cache是每个请求专属的,写多读少,而且可以在请求结束时就淘汰掉。对系统来说,把KV Cache放到远端内存池,最坏情况下只是每次新生成token时多一次轻微写入和偶尔的读取,对在线decode主链路的干扰远远小于把权重挪走。
3.2 一致性和故障管理,是解耦内存真正的深水区
很多人以为内存解耦的难点在物理和协议,可真到了生产环境,最头疼的是两类问题:一致性和故障域。
一致性方面,单机CXL扩展相对安全,因为硬件帮你维护了cache line粒度的一致性。但一旦做成多主机共享池,多个计算节点同时读写同一块远端内存,需要设计好锁和同步机制。CXL 3.0有一大进步就是支持了更细粒度的跨主机共享,但软件层面对“多主机同时搞同一块池子”的认知还非常初级。现实里很多团队根本不敢让多节点同时在线随机写一个共享区,基本都是用一块池切分成多个独立的“逻辑内存条”,一人一条互不干扰。
故障域是我最想提醒大家注意的坑。传统单机内存坏了,蓝屏/宕机就完,故障范围只有这台机器。解耦内存池裸奔的话,一个内存池控制节点挂掉,可能让成百上千个计算节点同时失去“标配内存”,那将是比单机宕机恐怖得多的群体性事故。设备商一般会告诉你CXL支持ECC、链路重传、RAS能力,但我在集群里做故障演练时还是踩过“远端内存控制器假死导致所有访问卡死”的坑。所以谁要是跟我说“内存池化之后可用性提升了”,我一定追问一句:池子本身挂了,你的调度器多久能感知、应用多久能切换、数据从哪儿找回?
3.3 数据放哪儿,比你买多大内存更重要
最后说工程里最容易被忽略的事情:数据放置策略。解耦内存不是买来插上就自动把性能变好,而是需要应用层明确告诉系统“哪块数据放HBM、哪块放CXL池、哪块可以直接丢到远端大池子”。
这里有一个我曾经被坑得很惨的例子。早期我做过一个评测,把某大模型的embedding表放到CXL扩展内存上,理论上embedding访问是离散小IO,延时不敏感,应该没什么影响。结果实际性能暴跌了30%以上。排查到最后发现,操作系统默认的自动NUMA均衡策略在疯狂迁移页面,每毫秒都在把远端页搬到本地,又把本地页换到远端,形成了典型的“页抖动”。后来关掉自动均衡、手动绑定内存策略,性能才恢复正常。
这类问题的本质是:操作系统和GPU驱动对“哪页该放在哪”的理解非常幼稚,它只在乎命中率,不在乎跨域迁移开销。你必须在应用层做分层:把每次iteration都在读的权重留在显存;把KV Cache这种低频但量大的数据划给内存池;把checkpoint、优化器状态这类几乎只在收敛点才用的数据放到更远、更大的池子。调度器再聪明,也聪明不过亲手把数据结构摸过一遍的人。
4. 要不要上解耦内存?三条决策路径和一份预算模板
4.1 先回答三个问题
不是所有团队都需要解耦内存。我建议任何准备上这个方案的团队,先回答三个问题:
- 当前算力还有多少余量?如果GPU利用率本来就低,瓶颈可能是代码和并行策略,不是内存。
- “单卡放不下”是长期稳定发生的,还是极端case?如果只有一次性的长上下文压测爆掉,加一张卡可能更便宜。
- 把内存扩到2倍/4倍,相比加同等算力的卡,成本节省多少?这个答案通常能帮你直接决定方向。
下面是我用来和客户对齐需求的分场景表格:
| 场景 | 典型配置 | 瓶颈 | 推荐方案 |
|---|---|---|---|
| 单机小模型推理、微调 | 1~8卡、单卡显存够放权重 | 并发KV Cache偶尔溢出 | CXL内存扩展卡,优先放KV Cache和embedding |
| 多租户云环境、多个小模型 | 多台GPU服务器,内存碎片化严重 | 每台服务器内存利用率低 | CXL内存池,动态分配,按租户切分QoS |
| 超大规模预训练、万亿参数 | 数百上千张卡 | 单机容量+跨机通信带宽 | NVLink域内显存共享/超节点内存池,传统CXL只放冷数据 |
4.2 一道简单的带宽/容量预算题
先说一个具体例子:70B模型,BF16权重,大概140GB。推理时KV Cache大小约等于2(K和V)× hidden_dim × 层数 × 2字节 × 序列长度。以80层、hidden_size=8192为例,每个token大约产生2.5MB的KV Cache,32K上下文就是84GB,128K上下文就是300GB以上。
假设你手头只有4张80GB的A100,总显存320GB。32K上下文时,权重140GB + KV Cache约84GB,加上激活值还能塞下;但到了128K长上下文,KV Cache逼近300GB,整台机器直接OOM。这时你有两个选择:加卡,或者把KV Cache放到内存池。
如果走内存池方案,生成每个token时,你需要的操作是:读一遍全部权重140GB(从HBM读),同时往内存池里写入这个token新增的KV Cache约2.5MB。注意,你并不需要在线decode时反复从头读KV Cache,只需要把写IO丢给池子。4卡A100本地HBM总带宽约8TB/s,读一遍权重大约要17.5ms;池子写入的那2.5MB即使走60GB/s的CXL带宽,也只是0.04ms的量级。也就是说,KV Cache放远端池,对在线生成延迟的影响非常小,但你把本地显存的240GB空间全部省给了权重和计算缓冲。
这个账算明白了,你就能理解为什么我说“不是所有内存都值得拥在本地”。真正决定在线推理性能的是热数据读取,而容量决定的是你能支撑多长的上下文、多少并发。把容量需求外包给解耦内存,把性能需求留在本地,是当前性价比最高的组合。
4.3 我的经验总结:解耦是为了“好钢用在刀刃上”
从我自己维护过的集群经验来看,解耦内存永远不会替代HBM,但它确实把“显存容量”从每张卡的天花板里解放了出来。实际操作中,我比较推荐从一个小实验开始,而不是一步到位建设几百TB的内存池。
这个小实验建议这样设计:拿一台GPU服务器,插一块CXL内存扩展卡,挑一个非高频依赖的数据结构(词表embedding、离线批量推理的KV缓存),把它映射到扩展内存上,跑一轮真实的业务流量,记录对比指标。如果收益不明显,大概率是你选错了对象;如果延迟上升但是QPS稳定,再考虑扩大池化范围。
我在多个集群里还见过一个共同教训:任何上了解耦内存的项目,都必须在设计之初就考虑“池子没了”的场景。内存池控制节点的故障演练、冷数据冗余、快速重新分配机制,一样都不能少。毕竟你迁移的不是文件,而是上千块GPU随时都在访问的“内存”,一旦故障,恢复的复杂度比文件系统高好几个级别。
说实话,内存墙到今天并没有被完全打破,解耦内存只是把墙推后了几步,让AI芯片能更聪明地利用已经存在但被闲置的资源。未来的CXL 3.1、更成熟的NVLink共享域、以及更智能的内存调度器,都会让这条路线越走越宽。但眼下,理解“什么该放近、什么可以放远、远的地方坏了怎么办”,才是所有AI基建人真正值钱的手艺。