长上下文为何昂贵:KV Cache 的存储账单

长上下文的真正瓶颈是 KV cache 带来的线性存储成本与注意力二次方计算开销。
文章指出,长上下文能力的核心瓶颈并非模型参数,而是推理时的 KV cache 内存开销。以 Llama 3.1 8B 为例,模型本身仅 16 GB,但 100 万 token 上下文的 KV cache 高达 128 GB,远超单张 H100 显存。KV cache 是 Transformer 避免重复计算的必然产物,其大小由层数、KV 头数、头维度和 token 数决定,每 token 开销为 128 KiB;70B 模型则达 320 KiB,1M 上下文需 344 GB。GQA 通过共享 KV 头将开销降低 4-8 倍。与此同时,注意力计算的二次方复杂度使长上下文成本双重上升。文章结论是:长上下文本质是一份存储账单,KV cache 预算规划应与模型选型同等重要。
长上下文不是免费的午餐
你的聊天记录可能比读取它的模型本身还要重。Llama 3.1 8B 是一个 16 GB 的模型,但如果给它一个 100 万 token 的提示,仅 KV cache 就需要 128 GB。这个对比揭示了一个常被忽视的事实:长上下文能力的真正瓶颈不是模型参数,而是推理过程中的内存开销。

据 Meta Llama 3.1 模型卡及 unsloth 配置数据,这一数字并非理论推演,而是基于实际部署配置的计算结果。当我们讨论"把上下文窗口扩展到 100 万 token"时,真正需要问的问题是:谁来为这些 token 的存储买单?
KV Cache 为什么存在
Transformer 架构本身没有记忆能力。早期的 RNN 维护一个固定大小的隐藏状态,虽然体积恒定,但会遗忘早期信息——这是经典的梯度消失问题。Transformer 则采取完全不同的策略:在每一个生成步骤中重新读取整个对话历史。
为了让这种"重新读取"不必每次从头计算,每个 token 在每一层都会被存储为 Key 和 Value 向量。存一次,永久复用。这个存储结构就是 KV cache。它让推理速度得以维持,但代价是显存占用的线性增长。
据 Sebastian Raschka 的分析,理解 KV cache 是理解大模型推理成本的关键——它不是可选的优化项,而是 Transformer 架构的必然产物。
KV cache 的具体定义与作用
KV cache(Key-Value 缓存)是 Transformer 推理时存储每一层每个 token 对应的 Key 和 Value 向量的数据结构。在自回归生成中,每生成一个新 token,模型需要计算它与所有历史 token 的注意力权重。如果不缓存历史 Key/Value,每一步都要重新计算整个序列的 K、V 矩阵,计算量会随序列长度平方增长。KV cache 通过缓存已计算的 K、V,使新 token 只需计算自身与缓存的注意力,将每步计算量从 O(n²) 降为 O(n),代价是显存占用随序列长度线性增加。
梯度消失与 RNN 的对比
梯度消失指 RNN 在反向传播时,梯度沿时间步连乘导致指数衰减,使模型难以学习长距离依赖。这直接造成 RNN 的隐藏状态虽固定大小,却会遗忘早期信息。Transformer 通过自注意力直接连接任意两个位置,绕开了这一问题,但代价是需要存储所有历史 token 的表示。
KV heads 与 head dim
在多头注意力中,每个注意力头独立计算 K、V。KV heads 指 Key/Value 投影的头数,head dim 是每个头的维度。标准多头注意力中 KV heads 等于查询头数,GQA 则让多个查询头共享一组 KV 头,从而减少缓存体积。
存储账单的计算方式
KV cache 的大小可以用一个简洁的公式表达:
cache = 2 (K and V) × layers × KV heads × head dim × tokens × 2 bytes
对于 Llama 3.1 8B,这个公式的结果是每 token 128 KiB。听起来不多,但规模化之后数字变得惊人:
- 128K 上下文:16 GB,与模型本身体积相同
- 100 万 token:128 GB,超过单张 H100 的显存容量
更大的模型付出更多。70B 版本每 token 需要 320 KiB,在 128K 上下文下占用 43 GB,在 100 万 token 时飙升至 344 GB。据 spheron 的 KV cache 指南,分组查询注意力(GQA)机制通过将 KV 头从 32 个减少到 8 个共享头,把这笔账单控制在可接受范围内——否则这些数字还要恶化 4 到 8 倍。
公式的推导与含义
2 (K and V) × layers × KV heads × head dim × tokens × 2 bytes 中,第一个 2 表示同时存储 Key 和 Value 两个张量;layers 是 Transformer 层数;KV heads × head dim 是每层每个 token 的 K 或 V 向量总维度;tokens 是序列长度;最后的 2 bytes 是 FP16(半精度)下每个参数的字节数。若使用 FP32,该值翻倍;使用 INT8 量化则减半。
GQA(分组查询注意力)
GQA 将查询头分组,每组共享一个 Key/Value 头。例如 Llama 3.1 8B 有 32 个查询头但仅 8 个 KV 头,使 KV cache 缩小为原来的 1/4。相比所有头共享一组 KV 的 MQA(多查询注意力),GQA 在质量和效率间取得更好平衡。
H100 显存与语境
NVIDIA H100 是当前主流 AI 训练/推理 GPU,常见 80 GB 显存版本。100 万 token 的 KV cache 需 128 GB,意味着单张 H100 无法容纳,必须多卡或借助 offloading 技术,这直观说明了长上下文的硬件门槛。
注意力机制的二次方叠加
内存只是账单的一部分。注意力机制的计算复杂度随序列长度呈二次方增长,这意味着更长的上下文不仅占用更多显存,还让每个词的处理成本上升。
这种双重压力——内存线性增长加上计算二次方增长——解释了为什么长上下文推理在实际部署中如此昂贵。据上述多源分析交叉验证,这一结论在 Meta 模型卡、unsloth 配置和 spheron 指南中均得到一致体现。
二次方复杂度的来源
自注意力计算中,每个 token 的查询向量需要与所有 token 的键向量做点积,生成 n×n 的注意力分数矩阵,因此计算量为 O(n²·d),其中 n 为序列长度,d 为维度。当 n 从 128K 增至 1M,计算量增长约 64 倍,而 KV cache 仅增长约 8 倍。这意味着即使显存足够,计算时间也会成为瓶颈。
常见缓解方法
FlashAttention 通过分块计算减少显存读写,提升实际速度但不改变理论复杂度;稀疏注意力、滑动窗口注意力(如 Mistral)只计算局部或部分注意力,将复杂度降至 O(n) 或 O(n log n);线性注意力则用核函数近似 softmax 注意力。这些方法各有取舍,目前尚未完全取代标准注意力。
长上下文是存储成本问题
长上下文不是一次内存升级,而是一份存储账单。在某个规模上,对话本身成为数据中心里最昂贵的对象。
这个视角的转变很重要:当我们评估一个模型的长上下文能力时,不应只看它支持多少 token,还要看每 token 的存储成本是多少。GQA 等架构优化能缓解问题,但无法改变线性增长的本质。对于构建长上下文应用的团队来说,KV cache 的预算规划与模型选型同等重要。
相关推荐

FlyEnv 插件实测:可视化运行 llama.cpp 与 GGUF 模型管理
FlyEnv 推出 llama.cpp 官方插件,提供多个 Metal 运行时并存管理、公共 GGUF 仓库索引与模型文件类型标注,以及上下文、线程、GPU 层数等推理参数可视化配置,支持模板与投机解码随模型保存,一键启动本地 LLM 推理服务。

前端如何进阶AI智能体开发?从OpenClaw拆解系统级Agent架构
从B站公开课演示的OpenClaw出发,拆解系统级AI智能体的三层架构与通用公式,分析前端开发者基于TypeScript切入Agent开发的路径、插件化设计与安全记忆层难点,附面试回答框架。

WorkBuddy实战:AI Agent如何自动批量转换与归档文件
通过B站UP主珊瑶老师的实测,对比豆包与WorkBuddy在文件批量转换任务中的表现,解析AI Agent如何从“给方案”到“直接执行”,附完整操作流程与积分消耗参考。