§ 01
问题:显存装不下所有会话
大模型每处理一个 token,都会在各注意力层留下一份 Key / Value 张量,这就是 KV Cache。有了它,生成下一个 token 时不必重新计算前面的上下文。上下文越长,这份缓存越大。
显存是有限的。本站测试平台的每张 AMD MI308X 有 192 GB HBM,除了放模型权重,还要放所有活跃会话的 KV Cache。会话一多,较早的缓存就被逐出。
被逐出的会话再发来请求时,模型只能把整段上下文重新预填充一遍。在 480B 模型、并发 16 的实测里,这样一次整段重算的首 token 延迟 p50 是 149.5 sR2。
§ 02
三层存放:显存、主机内存、外置全闪
KV Cache 分层按访问热度把缓存放在三种介质上。前两层由推理框架管理,第三层需要单独的存储设备,FX 系列做的就是这一层。
- 第一层,显存:放当前活跃的会话,三层里访问延迟最低,容量也最小。
- 第二层,主机内存:放近期用过的会话,由 LMCache 管理。
- 第三层,外置全闪:放全部历史会话,并让多个推理实例共享同一份缓存。
- L1
显存(HBM)
当前活跃的会话
由 vLLM 管理
- L2
主机内存
近期用过的会话
由 LMCache 管理
- L3
FX 全闪阵列
全部历史会话,跨实例共享
NVMe-oF · RoCEv2
§ 03
一次请求怎么走
命中一次外置缓存,就省掉一次完整的预填充。这是首 token 延迟下降的全部原因。
- 请求到达,LMCache 按输入 token 的前缀查找已有的 KV Cache。
- 显存里有,直接使用。
- 显存里没有,依次查主机内存和外置全闪;命中后把 KV Cache 读回显存,跳过这部分预填充。
- 各层都没有,才由 GPU 计算,并把新生成的 KV Cache 写入各层,供以后使用。
§ 04
实测:读回比重算快多少
测试对象是 Qwen3-Coder-480B-FP8,以八卡单实例(TP=8)的生产形态部署在 8 × AMD MI308X 上,负载是长上下文冷恢复。有两个对照基线,分母不同,不能混在一句话里说。
对比无外存、整段重算:加速 8.6–20×R2。并发 16 时,TTFT p50 从 149.5 s 降到 11.85 s。
对比本地 NVMe 单盘:吞吐提升 29–40%,TTFT p50 降低 26–32%R2R3。也就是说,同样是把 KV Cache 存下来再读,放在 FX100 上比放在服务器本地的一块 NVMe 盘上更快。
| 并发 | FX100 TTFT | 本地 NVMe 单盘 TTFT | 整段重算 TTFT | FX100 tok/s | 本地 NVMe 单盘 tok/s | 整段重算 tok/s |
|---|---|---|---|---|---|---|
| 8 | 7.53 s | 10.17 s | — | 56.6 | 43.9 | — |
| 16 | 11.85 s | 17.31 s | 149.48 s | 74.9 | 53.6 | 4.1 |
| 32 | 26.35 s | 35.73 s | — | 71.6 | 53.9 | — |
§ 05
为什么网络上的阵列比本地盘还快
§ 06
边界:什么时候没用
收益来自缓存命中。短对话、低并发的场景里,会话很少被逐出,也很少回来,命中率低,这层存储的收益就有限。
长上下文、多轮对话、Agent 和代码助手这类负载,会话恢复频繁,收益最明显。你的负载属于哪一种,要用自己的会话长度分布和并发量测过才知道。这也是我们坚持先联测、后采购的原因。
§ 07
软件栈与复现材料
外部参考资料
- 01Efficient Memory Management for Large Language Model Serving with PagedAttention · arXiv (SOSP '23)
vLLM 的 PagedAttention 显存管理与 KV Cache 分页的设计动机
- 02Mooncake: A KVCache-centric Disaggregated Architecture for LLM Serving · arXiv
以 KV Cache 为中心的存算分离架构,以及跨节点复用 KV Cache 的设计取舍
- 03
- 04
- 05
- 06