用 Llama-70B 跑一个 128K token 的长上下文请求,光是 KV Cache 就要占 429 GB 显存。
KV Cache 大小 = 2 × num_layers × num_heads × head_dim × seq_len × dtype_bytes
那么Llama-3.1-70B,FP16,seq_len = 128K token
= 2 × 80 × 8 × 128 × 131072 × 2 bytes
≈ 429 GB
H100 一块 80GB,429 GB 是什么概念,你得摆 5 块以上才够装这一个请求的 KV Cache。
这还不是什么极端测试,128K token 在今天的应用里已经很低了,代码库分析、长文档理解、多轮对话,随便哪个场景跑起来都需要更多的上下文窗口。
KV Cache,已经成了LLM 推理成本里最大的一块。
今天想聊聊三个可以直接用的工程手段,实测组合下来,长上下文推理成本能压 4 到 40 倍。
先说一下 KV Cache 是什么,不然后面没法聊。
Transformer 在推理的时候,每生成一个 token,都要去回顾之前所有 token 的 Key 和 Value 向量。不把这些存下来,就得每次重算,算到天荒地老。所以就有了 KV Cache,把这些中间结果存在显存里,下次直接拿来用。
问题是,序列越长,这个 Cache 就越大。上面那个 429 GB 的公式就是这么来的,不是玄学,就是线性增长,长度翻倍,Cache 翻倍。
好,背景交代完了,进正题。
第一把钥匙,TurboQuant,6 倍压缩,精度不掉。
这是 Google DeepMind 在 ICLR 2026 发的一个工作,核心想法很妙,让我忍不住多说几句。
我们都知道可以用量化来压模型,但 KV Cache 的量化一直有个老大难问题,它的各个维度方差极度不均匀,有的维度数值很大,有的基本是 0,用统一的标准去量化,精度就掉了。
TurboQuant 的解法是,先对 KV 向量做一次随机旋转。
你可能想,旋转一下有啥用。关键在于,正交旋转不改变内积,注意力机制的本质就是算内积,所以旋转完了计算结果还是对的。但旋转之后,原本七扭八歪的方差分布,就被均匀打散了,每个维度的分布都差不多。这时候再量化,每个维度都用最优的量化器,就不会浪费 bit,也不会丢精度。
更骚的是,这个旋转矩阵是随机生成的,不需要训练,不需要标定数据,即插即用。
实测下来,Llama-70B 配上 TurboQuant,128K 上下文的 KV Cache 从 429 GB 压到约 71 GB,两块 H100 就够了,benchmark 精度零损失。
GitHub 已经有 llama.cpp 的实现,加个启动参数就行,今天就能用,地址:https://github.com/TheTom/llama-cpp-turboquant。
第二把钥匙,PD 拆分,让首 token 延迟和吞吐量不再打架。
这个概念相对复杂一点,但理解了之后你会觉得,这是一个「为什么没早点这么做」的方案。
LLM 推理分两个阶段。第一阶段叫 Prefill,把你输入的 prompt 全部处理一遍,生成 KV Cache,这一步是算力密集型的,越长越慢。第二阶段叫 Decode,开始逐个生成 token,每次只算一个,是内存带宽密集型的。
问题是,如果把这两个阶段扔在同一台机器上跑,它们会互相抢资源。一个长 prompt 在做 Prefill 的时候,正在 Decode 的请求就被堵住了,用户感知上就是「一直在转,迟迟不出字」。反过来,如果为了让 Decode 顺畅,就得限制并发 Prefill,吞吐量又上不去。
解法就是:把两个阶段分到不同的机器上,中间用 KV Cache 传输连接。
比如LMSYS 跑 DeepSeek-R1(671B 参数的大模型)的方案是 96 块 H100,其中 24 块做 Prefill,72 块做 Decode,比例大约 1:3。这样两边可以独立扩缩,互不干扰,综合算下来,输出 token 成本是每百万 token 0.20 美元,差不多是官方 DeepSeek API 的五分之一。
vLLM 目前原生支持 PD 拆分,配置不算复杂,两套实例起来之后,指定一下角色就行。
第三把钥匙,LMCache,把 KV Cache 的钱花一次,用很多次。
前两把钥匙都在解决「单次请求的 KV Cache 太贵」的问题。LMCache 想的是另一层,能不能让同样的 KV Cache 复用到多次请求里?
比如你有一个很长的系统 Prompt,或者 RAG 里每次都会拼上的一批固定文档,这些内容每次请求都要重新计算 KV Cache,是纯纯的浪费。
LMCache 的做法是在 vLLM 上面加一层存储,把有相同前缀的 KV Cache 缓存下来,下次命中了直接拿,不用重算。存储分四级,GPU 显存、CPU 内存、本地 SSD、远端节点,按命中率动态调配,装不下就往下一级挪。
生产数字挺好看的,多轮对话场景,吞吐量能提升 15 倍。RAG 场景,如果文档集相对固定,prefill 计算量可以减少 60 到 80%。
接入方式就是换一行 pip install,再写一个 yaml 配置文件,入门成本很低。
三个工具叠在一起是什么效果?
TurboQuant 把每块 GPU 能装的 KV Cache 量提上去,PD 拆分让长 prompt 不再阻塞 Decode 吞吐,LMCache 让重复前缀的请求直接跳过 Prefill 计算,三层叠加,长上下文推理成本降 10 到 40 倍,具体看你的场景有多少重复前缀。
各自收益大概是这样,TurboQuant 6 倍内存压缩,PD 拆分 5 倍成本降低,LMCache 在高重复场景 15 倍吞吐提升。
怎么选用哪个组合?
上下文短的(8K 以内)、高并发场景,优先做 PD 拆分,TurboQuant 的收益在这里不明显。
上下文长的(32K 以上)、成本敏感的,TurboQuant 几乎是刚需,加上 LMCache 的 CPU offload,显存压力会大幅缓解。
RAG 或者多轮对话这类有大量重复前缀的场景,LMCache 是最大的杠杆,优先上它,固定文档集的前缀命中率基本可以到 100%。
单机部署、预算有限的,TurboQuant 加 LMCache CPU offload 就够用,不需要多节点,消费级显卡也能跑很长的上下文。
大规模集群,三件套都上,参考 LMSYS 跑 DeepSeek-R1 的 96 卡方案,成本降到竞品的五分之一。
最后说一个还在研究阶段但让我觉得挺有意思的方向,叫推理感知 KV 压缩。
现有的压缩方案对所有 token 一视同仁,但其实推理任务里,不同 token 的「重要性」差很多。数学题、代码生成这类推理链任务,在关键节点上模型需要精确的注意力,其他位置其实可以很粗糙。有个叫 TriAttention 的工作,根据推理重要性动态分配精度,关键位置 FP16,其他位置激进量化,在数学竞赛 benchmark 上,内存压缩 10.7 倍,精度基本不掉。
这个方向如果工程化成熟了,对 o3、DeepSeek-R1 这类推理模型的成本影响会很大。目前还在研究阶段,先放在这里,值得关注。
坦率地讲,这些技术都已经有成熟的开源实现,但真正用起来的团队还是少数。
KV Cache 是 LLM 推理成本的最大杠杆,这一点我现在是非常确信的。先把这几个工具接进自己的推理栈里,在同等预算下,能跑更长的上下文,能处理更多并发,这个差距会直接体现在产品体验上。
技术红利不等人。
以上,既然看到这里了,如果觉得不错,随手点个赞、在看、转发三连吧,如果想第一时间收到推送,也可以给我个星标⭐~
谢谢你看我的文章,我们,下次再见。