KV 缓存详解:长上下文为什么吃掉你的显存
更新于 2026-09-10 · 核实于 2026-08-04
每一句「本模型支持 128K 上下文」都跟着一个以 GB 计量的星号。这个星号就是 KV 缓存。
大多数人算显存只算权重,直到第一次把一百页 PDF 塞进对话框、显存瞬间爆炸。这篇把这笔账算清楚:KV 缓存是什么、怎么精确计算、以及显卡不够用时你能拧的三个阀门。
它是什么
Transformer 生成文本是一个 token 一个 token 来的。每生成一个新 token,模型都要让它「回头注意」前面所有 token——数学上,就是用新 token 的查询向量(Q)去和之前每个 token 的键(K)、值(V)向量做注意力运算。如果每生成一个 token 都把整段前缀重新算一遍,计算量随长度平方膨胀,聊几十轮就慢到不可用。
KV 缓存把这笔重复计算省掉:模型读取提示词时(prefill 阶段),把每个 token 在每一层算出的 K 和 V 向量全部存进显存;之后每生成一个 token(decode 阶段),只算新 token 自己的一份 K/V 追加进缓存,再读取整段缓存做注意力。生成变快了——代价是长对话和大文档会独立于模型权重吃掉显存。
两个直接推论:
- prefill 吃算力,decode 吃带宽。读提示词是大规模并行矩阵乘;生成是逐 token 串行,每步都要把全部权重和整段 KV 缓存从显存读一遍。上下文越长,每 token 要读的 KV 越多,生成越慢——本站速度估算只计权重读取,超长上下文的实际 tok/s 会比估算值再低一些。
- KV 和权重是两笔独立的账。权重加载完就固定了;KV 随实际上下文长度线性增长,一直涨到模型窗口上限或显存耗尽为止。
公式
KV 缓存(字节)= 2 × 层数 × KV 头数 × 头维度 × 每值字节数 × 上下文 token 数
逐项拆解:
2:K 和 V 各存一份。层数(num_hidden_layers):每层都有自己的一组 K/V,一层也逃不掉。KV 头数(num_key_value_heads):注意是 KV 头而不是查询头——GQA 架构里两者不相等,这是省钱的关键,下文详述。头维度(head_dim):每个注意力头的向量长度,通常等于 hidden_size ÷ 查询头数,现代模型多为 128。每值字节数:KV 的数据类型,默认 fp16 = 2 字节,开 q8 量化 = 1 字节。上下文 token 数:你实际使用的长度,不是模型标称上限。粗略换算:中文一字约 1 token,英文一词约 1.3 token。
手算一遍 Llama-3.1-8B:2 × 32 层 × 8 KV 头 × 128 维 × 2 字节 = 131,072 字节/token(128 KB)。拉到 128K token:131,072 × 131,072 ≈ 17.2 GB。作为对照,它的 Q4_K_M 权重只有 4.9GB(8.03B × 4.9 bit ÷ 8)——上下文吃掉的显存是模型本体的 3.5 倍。
各模型架构常数来自各自的 config.json:
| 模型 | 层数 | KV 头数 | 头维度 | 每 token | 8K 时 | 128K 时 |
|---|---|---|---|---|---|---|
| Llama-3.1-8B | 32 | 8 | 128 | 128 KB | 1.1 GB | 17.2 GB |
| Qwen3-32B | 64 | 8 | 128 | 256 KB | 2.1 GB | 34.4 GB |
| Gemma-3-27B | 62 | 16 | 128 | 496 KB | 4.2 GB | 66.6 GB |
| Llama-3.3-70B | 80 | 8 | 128 | 320 KB | 2.7 GB | 42.9 GB |
| gpt-oss-120b | 36 | 8 | 64 | 72 KB | 0.6 GB | 9.7 GB |
| DeepSeek-R1(MLA) | 61 | — | — | 69 KB | 0.6 GB | 9.2 GB |
全部按 fp16 KV、本站计算器同款公式计算(GB 按 10⁹ 字节)。Gemma-3 和 gpt-oss 实际使用滑窗注意力,真实占用低于表中公式值,见下文「公式是上限」。
再读一遍 Qwen3-32B 那行:128K 上下文时,KV 缓存(34GB)超过了 Q4 权重(20GB)。 一张「跑 Qwen3-32B 没问题」的 24GB 显卡,连它标称 32K 的上下文都碰不到,更别说 128K。
完整的显存账本:权重 + KV + 固定开销
KV 缓存从不单独出现。本站计算器的完整口径是:
总需求 = 权重(参数量 × 每参数字节数) + KV 缓存 + 1.5 GB 固定开销(CUDA 上下文/运行时)
拿最常见的 24GB 显卡(RTX 3090/4090)跑 Qwen3-32B(Q4_K_M,权重 20.1GB)算一遍:
| 场景 | KV 占用 | 总需求 | 24GB 判定 |
|---|---|---|---|
| 8K 上下文,fp16 KV | 2.1 GB | 23.7 GB | ⚠️ 刚好塞下 |
| 16K 上下文,fp16 KV | 4.3 GB | 25.9 GB | ❌ 单卡装不下 |
| 16K 上下文,q8 KV | 2.1 GB | 23.7 GB | ⚠️ 刚好塞下 |
| 32K(原生上限),q8 KV | 4.3 GB | 25.9 GB | ❌ 需要 32GB 卡 |
三个结论:24GB 卡跑 32B 模型,fp16 KV 下可用上下文只有 8K 左右;开 q8 KV 直接翻倍到 16K;想吃满 32K 原生窗口,得换 32GB 的 RTX 5090(25.9GB 落在紧张档),或者进一步压权重量化。
小显存是同一道题。12GB 的 RTX 3060 跑 Llama-3.1-8B(Q4_K_M 权重 4.9GB):32K 上下文总需求 10.7GB,能跑;64K 需要 15.0GB,超了;64K 配 q8 KV 又回到 10.7GB,又能跑了。q8 KV 是小显存卡换长上下文的第一手段。
判定口径:总需求 ≤ 可用显存 × 80% 为舒适,≤ 100% 为紧张。懒得手算就开显存计算器,选模型、拉上下文滑块,看 KV 那条柱实时变长。
GQA 已经救过你一次(只是你没注意)
早期 Transformer 用多头注意力(MHA):有多少查询头就有多少 KV 头。之后出现了极端的 MQA(所有查询头共享 1 个 KV 头),KV 极小但质量损失明显。GQA(分组查询注意力)是折中:查询头分组,每组共享一个 KV 头。2023 年的 GQA 论文证明它几乎不掉质量,自 Llama 2 70B 起成为主流架构。
效果有多实在?Qwen3-32B 有 64 个查询头,但只有 8 个 KV 头。如果它还是 MHA,128K 那行就要读成 275GB 而不是 34GB。GQA 把长上下文成本直接砍到八分之一。
但 GQA 的慷慨程度因模型而异。Gemma-3-27B 有 16 个 KV 头,每 token 496KB,是上表里最贵的(它靠滑窗注意力找补,见下节);同级别的 Mistral-Small-3.2-24B 只有 8 个 KV 头,160KB/token,长上下文成本差 3 倍。比较模型时,num_key_value_heads 和参数规模一样值得看:KV 头越少,长上下文越便宜。
MLA:DeepSeek 的压缩魔法
DeepSeek-R1/V3 走的是另一条路:不存完整 K/V,而是把每层信息压缩成一个 512 维潜在向量(kv_lora_rank),外加 64 维 RoPE 位置向量(qk_rope_head_dim)——每 token 每层只存 576 个值。61 层 × 576 × 2 字节 ≈ 69 KB/token。
这就是为什么 671B 的模型 KV 缓存比 Llama-8B 还小:128K 上下文只要 9.2GB,而 Llama-3.3-70B 要 42.9GB。我们的计算器为 MLA 模型使用独立公式——这也是 R1 的 128K 上下文(容量允许时)真正可用、而其他模型的 128K 只是宣传的原因。
代价只是换了科目:MLA 把显存压力转移到了权重——671B 参数,Q4 也要 411GB。没有免费午餐。
公式是上限:滑窗与混合架构
标准公式假设每一层都记住全部上下文。两类架构打破这个假设,真实 KV 低于公式值:
- 滑窗注意力(SWA):gpt-oss 系列一半层是滑窗层,只保留固定窗口内的 token;Gemma-3 每 6 层里 5 层用 1024 滑窗、只有 1 层全局。窗口层的 KV 不随上下文增长。
- 混合线性注意力:Qwen3.8-27B 每 4 层只有 1 层全注意力(其余是 Gated DeltaNet 线性层,KV 与上下文长度无关),标准公式对它高估约 4 倍;Muse-Glimmer-30B 是 3:1 的滑窗/全局混合,同理。
本站计算器对这些模型仍按标准公式算——宁保守勿乐观:公式值装得下,实际一定装得下。
上下文吃紧时的三个杠杆
- q8 KV 缓存(占用减半):质量代价对大多数任务可忽略,第一个该试。
- llama.cpp:
--cache-type-k q8_0 --cache-type-v q8_0(V 量化需同时开-fa闪注意力) - Ollama:环境变量
OLLAMA_KV_CACHE_TYPE=q8_0 - LM Studio:模型加载设置里的 KV Cache Quantization 效果:Llama-3.1-8B 在 128K 下从 17.2GB 降到 8.6GB。
- llama.cpp:
- 缩短上下文(线性节省):Ollama 默认上下文窗口只有 4096 token(旧版本为 2048),远小于模型标称上限——这就是你的实测显存比计算器估算低的原因。按任务定量:日常聊天 4–8K 足够;RAG 按检索片段总量估;整库代码或长文档才需要 32K+。改法:
/set parameter num_ctx 32768或 Modelfile 里PARAMETER num_ctx 32768;llama.cpp 用-c 32768。有意识的 32K 远好过默认的 4K 或盲目的 128K。 - 换架构(结构性解法):KV 头更少(Qwen3-30B-A3B 只有 4 个)、MLA(DeepSeek)、混合架构(Qwen3.8 / Muse)。这是买模型时的选择,不是买完后能拧的设置。
常见误区
- 「权重量化到 Q4,KV 也跟着变小」——不会。权重量化和 KV 量化是两个独立开关,运行时默认 KV 保持 fp16,哪怕权重是 Q2。
- 「支持 128K = 我的卡能用 128K」——标称窗口是架构能力,可用窗口是显存预算。两者的差值就是本文的公式。
- 「KV 就一份,多开对话没事」——每个并发会话各存一份。4 个 32K 并发的 Qwen3-32B,光 KV 就约 34GB(fp16);做自托管服务时,KV 往往比权重更早成为瓶颈。
- 「上下文调小会伤模型质量」——不伤。窗口只是记忆长度,不改变模型能力;超出的旧内容被丢弃,仅此而已。
- 「KV 大 = 模型强」——KV 成本是架构税,不是能力指标。Gemma-3 的 16 个 KV 头是架构选择而非质量承诺;MLA 缓存极小,模型却很强。
动手:三步算出任意模型的 KV 占用
- 打开模型 Hugging Face 页面里的
config.json,找三个数:num_hidden_layers、num_key_value_heads、head_dim(没有 head_dim 就用hidden_size ÷ num_attention_heads)。 - 套公式:2 × 层数 × KV 头数 × 头维度 × 2(fp16)× 目标上下文,除以 10⁹ 得 GB。MLA 模型(如 DeepSeek)改查
kv_lora_rank + qk_rope_head_dim,去掉那个 2。 - 不想手算:打开显存计算器选模型,把上下文滑块从 4K 拉到 128K,看 KV 那条怎么长。跑起来后用
nvidia-smi或ollama ps对照实际占用——差值通常来自框架默认上下文和你想的不一样。
KV 缓存不是实现细节,是你显存预算的另一半。买卡前、选模型前、设 num_ctx 前,先把这笔账算了。
常见问题
128K 上下文到底要多少显存?
Llama-3.1-8B 约 17GB——是 Q4 权重的 3 倍多;Qwen3-32B 约 34GB,超过权重本身。这就是为什么「支持 128K 上下文」和「你的显卡能用 128K 上下文」是两回事。
q8 KV 缓存伤质量吗?怎么开?
对大多数工作负载影响微小,是上下文吃紧时的第一选择。llama.cpp 用 --cache-type-k q8_0 --cache-type-v q8_0(V 量化需加 -fa),Ollama 设环境变量 OLLAMA_KV_CACHE_TYPE=q8_0,LM Studio 在加载设置里开 KV Cache Quantization。开启后 KV 占用减半。
为什么我的 Ollama 显存占用比你们计算器算的低?
Ollama 默认上下文窗口只有 4096 token(旧版本为 2048),远不是模型的最大上下文。比如 Llama-3.1-8B 在默认窗口下 KV 只有 0.5GB,自然显得省显存。我们的计算器允许你把上下文滑到模型的真实上限——差距就来自这里。
权重已经量化到 Q4 了,KV 缓存也会跟着变小吗?
不会。权重量化和 KV 量化是两个独立开关:运行时默认 KV 保持 fp16(每值 2 字节),哪怕你的权重是 Q2。想省 KV 显存,必须显式开启 KV 量化。
多开几个对话窗口,KV 缓存是共享的吗?
不共享。每个并发会话各存一份完整 KV。自托管 Qwen3-32B 服务 4 个 32K 并发,光 KV 就要约 34GB(fp16)——多用户场景下 KV 往往比权重更早成为瓶颈。