news 2026/9/15 3:14:59

主流LLM单Token KV Cache容量对比与推理显存规划指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
主流LLM单Token KV Cache容量对比与推理显存规划指南

一次线上服务,我把一个三万字的项目文档直接丢给大模型做长文本总结,结果显存一秒钟内被打满,服务直接 OOM 重启。后来排查原因时才发现,真正吃显存的不是模型权重,而是推理过程中不断累积的 KV cache。以前我也知道 KV cache 存在,但一直没认真算过它到底能占多大地方,直到被生产环境狠狠教育了一轮,才意识到单 token 的 KV cache 容量其实是个非常关键的指标,直接决定了你能跑多长的上下文、多大的并发,以及该买什么卡。

如果你也在做大模型推理部署,或者正准备在本地跑一个 7B 级别的开源模型做 Agent 应用,这篇文章值得花几分钟看完。我会把“主流 LLM 单 token KV cache 容量对比”这件事彻底讲透,包括计算公式、主流模型的横向对比、从单 token 推导到实际显存规划的方法,以及我在多次部署中踩过的坑和实测经验。

1. 单 token KV cache 到底在算什么

1.1 为什么每个 token 都要有一份 KV cache

要理解单 token 的 KV cache 容量,得先清楚 KV cache 是怎么来的。Transformer 结构里的自注意力机制在计算第 n 个 token 时,需要跟前面 n-1 个 token 做 Attention 计算。为了避免每次生成新 token 都把历史 token 的 Key 和 Value 全部重新算一遍,推理框架会把之前已经算好的 K 和 V 缓存下来,这就是 KV cache 的由来。

说白了,KV cache 就是“预计算好的历史注意力度量值”,它的存在让自回归生成从 O(序列长度²) 的重复计算降到了接近 O(序列长度) 的增量计算。但代价就是显存消耗随着序列长度线性增长,而且每个 token 都要存一份完整的 K 和 V,不管你后面用不用得上。这个“线性增长”听起来很温柔,实际算下来却很可怕。

1.2 单 token KV cache 的计算公式与参数解释

单 token KV cache 的大小由几个关键参数决定,公式可以拆成这样:

单token KV cache 字节数 = 2(K和V) × 层数 × KV头数 × head_dim × 每个元素字节数

其中:

  • 层数(num_hidden_layers):模型有多少层 Transformer block,每一层都要缓存一份 K 和 V。
  • KV头数(num_key_value_heads):这是影响最大的参数之一,跟注意力头数(num_attention_heads)不一定相等。
  • head_dim:每个注意力头的维度,一般是 64 或 128。
  • 每个元素字节数:取决于缓存精度,FP16 是 2 字节,INT8 量化后是 1 字节,FP8 也是 1 字节。

比如一个经典的 LLaMA 2 7B 模型,配置是 32 层、32 个 KV 头、head_dim 为 128,FP16 精度下算出来是:

2 × 32 × 32 × 128 × 2 = 524,288 字节 = 512 KB / token

一个 token 就要占 512KB,这还只是单份缓存的量,没算上 batch 和并发。如果上下文长度是 4096,那光是这一个序列的 KV cache 就达到 2GB 了。这也是为什么很多人在 7B 模型上稍微拉长上下文就跑不动的主要原因之一。

1.3 MHA、GQA、MQA 和 MLA 的巨大差异

这里必须展开说一下 KV 头数。传统 Transformer 用的是 Multi-Head Attention(MHA),每个 Q 头都配一个 K 头和 V 头,KV 头数等于 Q 头数。LLaMA 2 7B 就是这么干的,所以它的单 token KV cache 特别大。

后来大家发现,KV cache 占了太多显存,就有人提出用共享的方式减少 KV 头。Grouped-Query Attention(GQA)把 KV 头数降为 Q 头数的一个因子,比如 Q 有 32 个,KV 只有 8 个或 4 个。Multi-Query Attention(MQA)更狠,所有 Q 头共享同一组 K 和 V,KV 头数等于 1。这种改动直接影响单 token KV cache 的容量:同样层数和 head_dim 下,MHA 如果 KV 头是 32,GQA 的 8 头方案直接把它降到四分之一,MQA 更是降到三十二分之一。

最近像 DeepSeek 这类模型更进一步,用了 Multi-head Latent Attention(MLA),把 K 和 V 先压缩到一个低维 latent 空间再缓存,单 token KV cache 比同规模 MHA 模型小了一个数量级以上。这也是为什么 DeepSeek 敢把上下文窗口拉得很长,显存却依然扛得住的原因之一。所以看一个模型好不好部署,不能光看参数量,KV 头的设计可能比参数量对推理显存的影响更直接。

2. 主流模型单 token KV cache 容量横向对比

2.1 一张表看清主流开源模型的数据

我梳理了目前最常见的一批开源模型,按照官方配置和 FP16 精度手算了一遍单 token KV cache 容量,结果如下表。先说明一下,这里算的是理论值,不包含框架额外对齐、块分配导致的碎片,实际占用只多不少。

模型层数Q头数KV头数head_dim单token KV cache(FP16)
LLaMA 2 7B323232128512 KB
LLaMA 3 8B32328128128 KB
Mistral 7B32328128128 KB
Qwen2 7B28/3228/324128约 56-64 KB
Qwen2 72B80648128320 KB
LLaMA 2 70B80648128320 KB
DeepSeek V2/V3(MLA)60+多组1(压缩后)128约 8-16 KB 量级

从这个表能明显看出几个特征。同是 7B 级别的模型,LLaMA 2 7B 因为用了 MHA,单 token 512KB 是最大的;Mistral 7B 和 LLaMA 3 8B 用了 GQA,直接降到 128KB,只有前者的四分之一;Qwen2 7B 的 KV 头更少,单 token 只有 56KB 上下,在 7B 级别里属于非常省显存的设计。

70B 级别里,Qwen2 72B 和 LLaMA 2 70B 虽然参数量大,但因为 KV 头数压到了 8,单 token 320KB 甚至比 7B 的 LLaMA 2 还要小。所以不能简单认为“模型越大 KV cache 越大”,KV 头数的设计才是主导因素。至于 DeepSeek 的 MLA 结构,它在缓存前做了压缩,单 token 容量跟传统 GQA 模型已经完全不在一个数量级,这也是它能以极高性价比支持超长上下文的核心原因之一。

2.2 为什么同属 7B 级别差距这么大

有人可能会奇怪,都是 7B 的模型,为什么 KV cache 差距能到 8 倍以上。原因在于参数量主要分布在 embedding 和 FFN 层,注意力层里的 KV 参数在整个模型里占比并不高,但是 KV cache 的量恰好只跟注意力层的结构有关,跟 FFN 层一点关系都没有。

所以模型设计者可以在保持总参数量不变的前提下,通过 GQA 把 KV 头数从 32 砍到 8,参数量可能只损失几个百分点,但 KV cache 直接缩小四倍。这种“牺牲一点点精度换取推理效率”的折中方案,在面向长上下文和并发推理的场景里非常划算。我实测下来,在长文本摘要和 Agent 多轮对话场景里,GQA 模型的精度损失基本感知不到,推理吞吐却有肉眼可见的提升。

2.3 精度对单 token 容量的影响

上面表格算的是 FP16 精度的默认值。如果使用 INT8 或 FP8 做 KV cache 量化,单 token 容量直接减半。比如 Mistral 7B 的 128KB 会变成 64KB,同样一块 24GB 的卡能多撑一倍的上下文长度。

这里提醒一句,KV cache 量化跟模型权重量化是两回事。模型权重可以用 4bit 量化(比如 GPTQ 或 AWQ),但 KV cache 目前的主流方案是 8bit 或者直接保持 FP16,少数场景用 4bit 但精度损失比较明显。有些框架(比如 vLLM)支持 kv_cache_dtype 参数单独控制缓存精度,建议按任务需求来设置,不要盲目追求低精度。

3. 从单 token 数值推导真实推理显存规划

3.1 一个公式估算 KV cache 总占用

知道了单 token 的 KV cache 容量之后,推理时的总占用就很好估算了:

KV cache 总显存 = 单token KV cache 容量 × 总序列长度 × 并发序列数(batch size)

这里的“总序列长度”要特别小心,不只是输入长度,而是输入加上输出长度之和。很多人算显存时只算了 prompt 的长度,忘了生成阶段每个新 token 都会继续往 KV cache 里追加,导致部署后跑到一半爆显存。

举一个我实际遇到过的例子。用 Mistral 7B(单 token 128KB)跑多轮 Agent 场景,一个会话输入 2000 token,输出 2000 token,总长度 4000,那一个序列的 KV cache 是:

128KB × 4000 = 512,000 KB ≈ 500 MB

看起来不大,但如果同时有 16 个用户会话在跑,KV cache 就是 8GB。再加上模型权重 14GB(FP16)、激活值、CUDA context 等开销,24GB 的卡就非常紧张了。这也是为什么很多 Agent 框架跑多轮对话时,并发稍微一高就 OOM。

3.2 实际部署中的显存预算清单

我自己做推理服务时,通常按下面这个思路估算整张卡的需求:

  • 模型权重:7B FP16 大约 14GB,8bit 量化约 7GB,4bit 量化约 4GB。
  • KV cache:按单 token 容量 × 预估最大总长度 × 最大并发计算。
  • 激活值:跟 batch size 相关,通常预留 1-2GB。
  • CUDA context 和框架开销:vLLM 通常预留 1-2GB。

全部加起来如果接近或超过显存上限,就要优先考虑几个手段:换 GQA/MLA 架构的模型,降低 KV cache 精度,限制单序列最大长度,或者调低最大并发数。在 vLLM 里,max_num_seqs 和 max_model_len 这两个参数本质上就是控制 KV cache 池子大小的,理解单 token 容量后,就能非常直观地知道该把它们设成多少。

3.3 PagedAttention 与 KV cache 碎片问题

vLLM 这类框架引入的 PagedAttention,把 KV cache 分成固定大小的块来管理,类似操作系统里的分页机制。它不改变单 token 的 KV cache 容量,但能显著减少内存碎片,并允许不同序列共享相同的 prompt 前缀缓存。

实际使用中,prefix caching 在 Agent 场景效果很明显。比如系统提示词有 2000 token,如果每轮对话都重新存一遍,那每个新会话都要白白多占 2000 token 的 KV cache;开启前缀缓存后,这部分可以共享,只有当用户输入和系统提示词都相同的前缀才能命中,所以对场景有要求。但不管怎样,理解单 token KV cache 的容量,能帮你在估算显存时更精准,而不是稀里糊涂地靠试错调配参数。

4. 实测 KV cache 容量与常见部署问题实录

4.1 如何通过日志和监控拿到真实 KV cache 数值

理论计算只是第一步,真正部署时还要用工具验证。vLLM 在启动时会打印一行日志,里面包含 KV cache size 的信息,比如:

KV cache size: 4.00 GB, max_num_seqs: 32, max_model_len: 4096

这行日志直接告诉你框架为 KV cache 预留了多少显存。我一般会拿这个数字除以最大并发再除以最大长度,反推一下单 token 实际容量,用来校验框架是否开启了量化或其他优化。如果算出来的数字明显小于理论值,大概率是框架默认启用了 KV cache 量化或者块大小做了对齐。

如果你用的是 HuggingFace 原生的 generate 接口,可以通过 nvidia-smi 监控显存随生成长度的变化趋势。思路是固定 batch size,逐渐增加输入长度,观察显存增长的斜率,这个斜率就是单 token 的实际 KV cache 占用,测出来的数值会比手算可靠得多。

4.2 常见问题速查:KV cache 相关的坑

我在部署过程中遇到过不少问题,挑几个典型的整理成表,方便大家排查:

现象可能原因排查思路与建议
一跑长上下文就 OOM只算了输入长度,没算输出累积用“输入+输出”总长度重新估算 KV cache
单卡并发很低就显存不足模型权重太大 + MHA 结构换 GQA/MLA 模型,或开启 KV cache 量化
不同框架跑同一模型显存差异大是否开启 PagedAttention、前缀缓存、块对齐查看框架日志里的 KV cache size 对比
开启量化后精度明显下降KV cache 压到 4bit 以下至少用 8bit,关键任务保持 FP16
长文档摘要时开头容易被“遗忘”KV cache 溢出被截断检查 max_model_len 设置,或换更长上下文版本模型

4.3 关于 KV cache offload 和 CPU 卸载的一点经验

当显存实在不够时,还有一个很粗暴的方案:把 KV cache 卸载到 CPU 内存。vLLM 的 cpu offload 和 DeepSpeed 的 ZeRO-Inference 都支持类似能力。但我实测下来,这个方案只适合离线批处理场景,在线实时推理里 CPU 和 GPU 之间的 PCIe 传输延迟会直接拖垮首 token 速度,用户体感会非常明显。

如果你的场景是长文档离线分析、批量知识库问答,那 CPU offload 牺牲一点速度换取更长的上下文,是可以接受的。但如果是实时聊天类应用,我建议优先从模型选型下手,选一个单 token KV cache 容量更小的模型,比什么花哨的 offload 方案都管用。

4.4 KV cache 容量的选择对 Agent 场景的实际影响

最近 Agent 类应用非常流行,这类应用的核心特征是系统提示词长、多轮对话多、上下文会持续累积。我做 Agent 服务时,对 KV cache 的感受是最深的。同样跑 8 个并发会话、每轮 4000 token 上下,Mistral 7B 的 KV cache 需要 4GB,Qwen2 7B 只需要约 1.8GB,差距接近一倍。这意味着在同样的卡上,Qwen2 7B 能支撑的并发量明显更高,或者可以支撑更长的上下文而不需要频繁截断历史。

所以现在我做技术选型时,会把“单 token KV cache”作为一个独立指标,跟模型的 MMLU 分数、代码能力放在一起对比。很多时候一个模型能力稍微弱一两个点,但 KV cache 省一半,反而更适合实际生产环境。这算是我踩过几次坑后总结出的一个朴素经验。

5. 单 token KV cache 在长上下文和并发场景的工程参考

5.1 一张卡到底能撑多少并发?直接算给你看

有了单 token KV cache 这个基础指标,很多部署决策就能直接心算。举个例子,假设有一张 24GB 的卡,跑的模型是 Qwen2 7B,模型权重 FP16 约 14GB,剩下约 10GB 给 KV cache、激活值和 CUDA 开销。单 token KV cache 按 56KB 算,如果限定单序列总长度 4096,那理论上最多能支撑的并发序列数是:

10GB 可分配 KV cache ≈ 10 × 1024 × 1024 KB ≈ 10,485,760 KB 每个序列 KV cache = 56KB × 4096 ≈ 229,376 KB 并发上限 ≈ 10,485,760 ÷ 229,376 ≈ 45

当然这是理想值,实际还要扣掉激活值和预留空间,打个六折也有 27 个并发左右。如果是 Mistral 7B 的 128KB 单 token 容量,同样条件下并发上限就只有 20 个左右,能满足的连接数明显要少。这个差距在商业服务中直接决定了要买几张卡,算下来是真金白银的差别。

5.2 长上下文场景的显存增长曲线

我还整理过一张更直观的对照表,固定并发为 1,只看单个序列的 KV cache 在不同长度下的增长趋势:

上下文长度LLaMA 2 7B 的 KV cacheQwen2 7B 的 KV cache
1024512 MB约 56 MB
40962 GB约 224 MB
81924 GB约 448 MB
3276816 GB约 1.8 GB

从这里可以看出,LLaMA 2 7B 跑到 32K 上下文时,光是 KV cache 就是 16GB,很多卡直接出局;而 Qwen2 7B 在同样长度下只需要 1.8GB,还有余量给权重和激活值。这就是为什么同样支持长上下文的模型,实际部署成本可能差好几倍。

5.3 做技术选型时如何利用这个指标

以我个人的经验,选模型时可以把单 token KV cache 容量作为一个固定筛选条件。如果你要做一个 7B 级别的服务,且预期并发不低,那就优先看 KV 头数比较小的模型;如果你要跑 70B 级别,那 KV cache 的设计好坏几乎决定了能不能用单卡或双卡跑起来。结合前文的计算公式和实测方法,选型时已经不需要靠猜了,直接手算一遍就能知道这个模型在你的硬件上大概能跑到什么程度。

这个思路不仅适用于开源模型,也适用于理解厂商提供的 API 定价差异。有些服务商按 token 收费,但实际推理成本差异很大,单 token KV cache 很小的模型,提供长上下文服务的边际成本会更低,定价自然也可能更有优势。理解了这个底层逻辑,跟技术选型、成本预算相关的事情都会清晰不少。

写在最后

我现在的习惯是,拿到一个新模型先不看排行榜分数,而是先把 config.json 里的层数、KV 头数、head_dim 拿出来,手算一下单 token KV cache,再去估显存和并发。这个习惯帮我避开了好几次买错卡、选错模型的坑。KV cache 这个看似底层的小参数,实际上决定了你在真实业务里能不能跑得动、跑得值。

最后再分享一个小技巧:如果你在用 vLLM 部署,启动时可以在日志里确认 KV cache size,然后结合你的实际请求模式,动态调整 max_model_len 和 max_num_seqs,而不必追求极限长度或极限并发。很多时候,一个合理的默认值能帮你省下大量调优时间,让服务稳定跑上几个月不出问题。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 3:14:53

Linux文件查看与终端快捷键:cat、more的高效使用指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/15 3:14:30

移动端发热优化:纹理压缩与后处理带宽优化实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/15 3:13:47

2026国内AI Coding工具选型实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/15 3:12:04

Vivado/Vitis 2024.2.1升级安装器找不到旧版本?三个修复方案实测

1. 问题现场:升级 2024.2.1 时,安装器死活找不到你已经装好的 Vivado手里的 Vivado/Vitis 2024.2 用得好好的,结果看到 2024.2.1 更新说明里正好列了几个我踩过的 bug 修复项,比如 Vitis 里某个版本的链接报错、Vivado 仿真库在部…

作者头像 李华
网站建设 2026/9/15 3:11:14

Keil添加文件闪退原因排查与解决全攻略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华