
大模型推理是这两年最热的技术方向之一但很多人跑通 demo 之后一遇到“为什么并发上不去”“为什么显存不够用”“为什么首 token 慢但后续 token 相对快”这些问题就卡住了。这三个问题其实都指向同一个核心机制KV Cache。面试笔试高频考点这个标签不是夸张无论你是做推理优化、模型部署还是做大模型应用开发KV Cache 都是绕不开的基础概念。这次我们就把 KV Cache 的原理、显存计算、token 复用逻辑和工程优化方向一次性讲清楚顺便拆解几道常见面试题。先给出本文的核心结论KV Cache 的本质是用显存换算力把自回归生成过程中重复计算的 Key 和 Value 缓存下来避免每一步都重算历史 token 的注意力结果。没有 KV Cache大模型生成速度会慢一个数量级但有了 KV Cache显存占用又会随着序列长度线性增长。所以 KV Cache 不是简单地“开启”就完事它还牵扯到显存管理、批处理策略、缓存命中率和系统吞吐量之间的平衡。本文会从自回归机制讲起逐步拆到显存公式、token 复用、vLLM 等推理框架的优化思路最后给出面试应对建议。如果你正在做大模型本地部署、接口服务调优或者准备大模型方向的面试这篇文章建议收藏。1. 核心概念速览在展开原理之前先把 KV Cache 涉及的核心概念和常见考点列出来方便对照阅读。概念一句话解释常见考点自回归生成模型每次只生成一个 token新 token 依赖之前所有 token为什么生成必须逐 token 进行Attention 计算每个 token 都要计算与历史 token 的相关性Q、K、V 矩阵的形态变化K / V 矩阵Key 表示 token 的“索引标识”Value 表示 token 的“内容特征”K、V 的维度和层数KV Cache缓存历史 token 的 K、V 矩阵供后续 step 复用为什么 Q 不缓存预填充阶段 Prefill处理输入序列并行计算首 token 的 KV Cache为什么首 token 延迟往往较高解码阶段 Decode逐 token 生成每一步只计算新 token 的注意力为什么后续 token 生成速度相对稳定显存增长KV Cache 大小与序列长度、层数、头数、精度线性相关给定参数估算显存占用Token 复用相同前缀的请求可以共享前缀 KV Cache多轮对话、few-shot 场景省算力并发限制Batch 内所有序列的 KV Cache 同时驻留显存为什么大并发容易 OOM工程优化PagedAttention、前缀缓存、量化 KV 等技术vLLM、SGLang 等推理框架的优化点这张表看完你对 KV Cache 在推理链路中的位置应该有了基本坐标。下面进入正题。2. 大模型为什么要做自回归生成要理解 KV Cache首先得理解大模型生成 token 的基本方式。以 ChatGPT 这类 decoder-only 模型为例它的生成过程不是一次性吐出完整句子而是像打字一样一次只生成一个 tokentoken 可以粗略理解为一个子词或字符片段。生成第 t 个 token 时模型需要把前面 t-1 个 token 和当前 step 的输入一起送入模型计算得到下一个 token 的概率分布然后通过采样策略top-p、temperature 等选出最终输出。这个过程用公式表达就是P(x_t | x_1, x_2, ..., x_{t-1})也就是给定前文预测下一个 token 的条件概率。这种“自己生成的内容继续作为输入”的方式就是自回归。自回归带来的直接后果是token 是一个接一个生成的生成速度天然受限于 step 数。一个 100 token 的回答至少需要 100 次前向推理。KV Cache 的作用就是让这 100 次前向推理中除了第一次预填充后面的每一步都不需要从头计算历史 token 的注意力。如果把 KV Cache 去掉每次生成新 token 都要把完整的历史序列重新过一遍模型。假设序列长度为 N去掉 KV Cache 后生成第 N 个 token 时模型要对 N 个历史 token 重复计算注意力计算量接近 O(N²)。而启用 KV Cache 后只要一次预填充预计算好历史 K、V后面每一步计算量只和当前 step 相关整体计算量从 O(N²) 降为 O(N) 级别。这也是 KV Cache 在推理中不可或缺的根本原因。这里要区分两个阶段预填充阶段Prefill和解码阶段Decode。预填充阶段处理完整的输入提示词并行计算每个输入 token 的 K、V并写入缓存。这个阶段计算量大但并行度高所以首 token 延迟主要取决于输入长度和 GPU 算力。解码阶段逐 token 生成新 token。每一步只计算新 token 的 Q、K、V并用新 K、V 与缓存中的历史 K、V 做注意力计算生成下一个 token。预填充阶段是“一次算完”解码阶段是“一步一算”。KV Cache 的作用区间主要集中在解码阶段。3. Attention 机制里的 Key、Value 到底缓存了什么很多教程讲到 KV Cache 会直接说“缓存了历史 token 的 K 和 V”但 K、V 到底是什么为什么要缓存它们很多人并没有真正搞懂。注意力机制的核心公式是Attention(Q, K, V) softmax(Q * K^T / sqrt(d_k)) * V在一个完整的注意力头中QQuery表示当前 token 要“查询”什么。它代表当前生成位置的需求。KKey表示每个历史 token 的“索引标识”。模型通过计算 Q 与所有 K 的点积判断历史 token 中哪些与当前位置相关。VValue表示每个历史 token 携带的“内容信息”。在获得注意力权重后用权重对 V 做加权求和得到当前位置的输出。生成新 token 时Q 肯定是新的因为当前位置变了查询需求也变了。但 K、V 是历史 token 的固有属性输入序列中第 3 个 token 的 K、V在生成第 4、第 5、第 100 个 token 时都不会变。换句话说历史 token 的 K、V 是“只算一次反复使用”的。这就解释了为什么缓存的只有 K 和 V而不缓存 Q。Q 是每个新位置新算出来的没有复用价值。K、V 是历史上下文的“记忆”只要上下文不变K、V 就不变所以它们可以被缓存。实际计算过程可以用一个简单的例子模拟。假设当前序列有 4 个 token[我, 爱, 学习, AI]。要生成第 5 个 token 时把输入AI送入模型计算得到它对应的 Q、K、V。用这个新 Q与缓存的第 1 到第 4 个 token 的 K 做点积得到注意力分数。用 softmax 归一化后与缓存的历史 V 和新 V 做加权求和。得到 attention 输出送进 FFN最终预测下一个 token。在这个过程中历史 4 个 token 的 K、V 不需要重新计算这就是 KV Cache 的作用。4. 从零开始计算 KV Cache 的显存占用KV Cache 最大的代价是显存。在大模型部署场景KV Cache 往往比模型权重本身更占显存。这里给出一套手算方法方便你自己估算。KV Cache 的大小由以下几个变量决定num_layers模型的层数 num_kv_headsKV 头的数量如果使用 GQA 或 MQAKV 头数小于 Query 头数 head_dim每个注意头的维度 sequence_length序列长度 batch_size同时处理的请求数 dtype_bytes数值精度字节数FP16/BF16 为 2 字节每个 token 的 KV Cache 显存计算公式为KV Cache 大小字节 2K 和 V 两份 × num_layers × num_kv_heads × head_dim × sequence_length × batch_size × dtype_bytes举例说明。设一个模型的参数为层数 32 KV 头数 8 head_dim 128 序列长度 2048 batch_size 1 精度 FP162 字节计算单个 token 的 KV 显存单 token KV 2 × 32 × 8 × 128 × 2 131,072 字节 128 KB2048 个 token 的序列总 KV 128 KB × 2048 256 MB也就是说一个 2048 token 的请求在 batch_size 1 时光是 KV Cache 就要占 256 MB 显存。如果并发 10 个请求就是 2.5 GB这还是在模型权重之外额外占用的。如果换成 32 个 KV 头即传统 MHA 结构单 token KV 显存翻 4 倍2048 token 序列就要 1 GB 显存。这也是为什么现在新模型普遍使用 GQA分组查询注意力或 MQA多查询注意力的原因——减少 KV 头数就是直接减小 KV Cache。使用 Python 可以写一个简单的估算函数def estimate_kv_cache_gb( num_layers32, num_kv_heads8, head_dim128, seq_len2048, batch_size1, dtype_bytes2, ): kv_bytes_per_token ( 2 * num_layers * num_kv_heads * head_dim * dtype_bytes ) total_bytes kv_bytes_per_token * seq_len * batch_size total_gb total_bytes / (1024 ** 3) return total_gb # 示例估算 print(estimate_kv_cache_gb(seq_len2048, batch_size1)) print(estimate_kv_cache_gb(seq_len4096, batch_size16))这个公式理解之后很多问题就能自己解释了为什么模型允许的上下文越长显存要求越高因为 KV Cache 随序列长度线性增长。为什么并发数上不去因为每个请求的 KV Cache 都驻留在显存中。为什么长上下文中后段生成速度变慢除了注意力计算量增加还会因为 KV Cache 越来越大显存带宽读取压力增大。实际显存占用还需考虑模型权重、激活值、CUDA context 等KV Cache 只是其中一部分但通常是最容易在长上下文场景下被忽视的那部分。5. Token 复用逻辑前缀命中与上下文遗忘KV Cache 的另一个关键应用场景是 token 复用即多个请求之间存在相同的 token 前缀时可以共享这部分 KV Cache避免重复计算。最典型的场景是多轮对话。假设你和一个模型连续对话用户介绍下 Python 助手生成了 500 token 的回答 用户再给个代码示例在第二轮请求时第一轮的“用户输入 助手回答”作为历史上下文传入模型。如果没有 KV Cache 复用模型需要从头重新计算第一轮所有 token 的 K、V这是巨大的浪费。如果系统在前一轮已经缓存了这些 token 的 KV Cache那么第二轮请求只要直接读取缓存计算新输入的 KV 即可。这就是“token 复用逻辑”在生产环境中的实际含义。它对推理系统性能的影响非常大主要体现在三方面。第一减少了预填充阶段的计算量。预填充是计算密集型的如果前缀命中缓存这部分算力直接省掉首 token 延迟显著降低。第二提升了吞吐量。同样的 GPU 算力在缓存命中情况下单位时间能处理更多请求。第三降低了显存占用波动。每个请求不再需要为完整历史上下文分配新的 KV Cache而是复用已有缓存块。实现 token 复用的代表性技术包括框架或技术核心思路vLLM PagedAttention将 KV Cache 分块管理支持块级共享减少显存碎片SGLang RadixAttention以字典树Radix Tree结构管理前缀实现高效前缀复用OpenAI / Anthropic API服务端维护缓存相同前缀的请求自动命中缓存降低延迟和成本这里需要强调一个容易混淆的点缓存命中Cache Hit指的是 KV Cache 的复用不是 Prompt 字符串级别的简单地“查到上一次答案”。即使两次请求的文本前缀完全相同模型依然要执行注意力计算参与推理只不过历史部分的 K、V 直接读缓存不需要重新算。还有一个实际工程问题token 复用可能导致“缓存污染”。当用户的输入前缀在缓存中存在巨大占用但后续内容完全不同时这些缓存块如果长期不被再次命中会白白浪费显存。推理框架通常会采用 LRU 或 LFU 之类的淘汰策略来管理缓存块控制缓存大小和命中率之间的平衡。6. KV Cache 对推理速度、显存与并发的实际影响KV Cache 不是一次设置就永远最优的配置它对系统性能是动态影响的。下面从三个角度来分析速度、显存和并发。6.1 对推理速度的影响启用 KV Cache 后生成阶段的单步计算量确实变小了但 KV Cache 本身会带来显存带宽压力。注意力计算需要读取所有历史 token 的 K、V序列越长KV Cache 越大单步生成时需要读取的数据量就越大。这种读取是显存带宽密集型的尤其是长上下文场景下GPU 计算单元大部分时间在等待数据从显存搬运到计算单元。如果你自己跑过生成任务就会发现短上下文时生成速度基本稳定但当上下文长度接近模型上限时每个 token 的生成耗时明显增加。这就是 KV Cache 带来的带宽瓶颈。6.2 对显存的影响KV Cache 是驻留在显存中的。如果一个 GPU 的显存是 24 GB模型权重量化后占 6 GB那么剩下的约 18 GB 中还要留给激活值和 CUDA context 一部分实际能分配给 KV Cache 的空间大概只有 10 到 15 GB。在这个限制下能同时容纳多少并发请求、多长的序列就是一套组合约束。常见的问题表现是单条长文本请求可以跑但并发一上来就 OOM或者短文本没问题长文本加载到一半显存就爆了。这些都可以用上面的公式快速定位原因。6.3 对并发吞吐的影响推理系统在服务多个请求时会把多个请求组成一个 batch 一起进入 GPU 计算。但这个 batch 中每个请求都有自己独立的 KV Cache。batch 越大KV Cache 总量越大显存压力越大。如果显存不足最常见的手段是降低最大 batch size但这又会导致 GPU 利用率下降吞吐量上不去。这里有一个关键思路是 Continuous Batching连续批处理。传统静态批处理需要等到 batch 中所有序列生成完毕才能释放而连续批处理允许新的请求在旧请求结束前插入空位。vLLM 的 PagedAttention 就是在此基础上通过分页方式管理 KV Cache只有在需要时才分配新的缓存页显存碎片大幅减少相同显存下可以容纳更多并发请求。这也是 vLLM 这类推理框架在吞吐量上比 naive 实现高很多的核心原因之一。实际业务中观察推理系统状态时建议重点盯三个指标1. TTFTTime To First Token首 token 延迟反映预填充速度和前缀命中情况。 2. TPOTTime Per Output Token每个输出 token 的耗时反映解码阶段速度和 KV Cache 读取压力。 3. Max Concurrency / Max Batch Size最大并发数反映 KV Cache 显存预算。配套的观测工具可以使用 nvidia-smi 监控显存使用推理框架自带的 metrics 接口看吞吐和缓存命中率。7. 面试高频考点与答题思路KV Cache 是大模型推理方向面试的高频考点。这里整理几个常见问题并给出答题要点供考前快速过一遍。7.1 为什么只需要缓存 K 和 V不缓存 Q核心答题思路Q 是当前解码位置动态生成的查询向量每个新 token 都有自己的 Q没有复用价值。K、V 是历史 token 的固有向量同一 token 在后续解码中不再变化复用价值高所以缓存 K、V。7.2 KV Cache 的显存占用怎么计算答题时先给公式再代入例子。公式见第 4 节面试时手算一个大致的量级即可。重点说清楚四件事层数、KV 头数、序列长度、精度。7.3 KV Cache 在长上下文场景下会遇到什么问题注意力机制本身计算量为平方级KV Cache 是线性增长但在超长上下文下会产生两个主要问题一是显存占用过大二是解码阶段读缓存带宽压力大。解决方案包括 GQA/MQA、滑动窗口注意力、稀疏注意力、KV Cache 量化、以及 PagedAttention 的分块管理。7.4 vLLM 为什么比传统推理方案吞吐高关键点在 PagedAttention把 KV Cache 按固定大小的块Page分配块之间通过索引关联不需要连续显存解决了显存碎片问题同时支持块级前缀共享相同的 Prompt 前缀可以被多个请求复用。显存利用率提升之后相同资源下能容纳更大的 batch吞吐量自然提升。7.5 Prefill 阶段和解码阶段为什么需要分开优化Prefill 阶段是计算密集型的显存占用相对小要最大化 GPU 计算并行度Decode 阶段是内存带宽密集型的单步计算量小要把重心放在减少 KV Cache 读取开销和批处理管理上。这也是很多推理框架把这两个阶段拆分调优的原因。7.6 缓存命中率对成本有什么影响在多轮对话、Agent 调用、固定 system prompt 等场景中如果前缀相同但每次都全量重算预填充的计算开销会重复浪费。提高前缀缓存命中率能显著降低 TTFT减少算力消耗对按 token 计费的 API 服务来说也能降低端到端成本。8. 常见误区与排查思路KV Cache 相关的坑主要集中在理解和工程两个层面这里列出几类高频问题。问题现象可能原因排查方式解决方案显存只加载了模型却很快 OOMKV Cache 占用了剩余显存且不断增长用 nvidia-smi 监控显存变化趋势限制最大序列长度、减少并发、开启 PagedAttention并发一高就 OOMbatch 内 KV Cache 总量超预算计算单请求 KV 显存再乘并发数降低最大 batch size或升级显存长文本生成速度明显下降KV Cache 读取带宽受限对比不同长度下的 TPOT 数据启用 KV Cache 量化或改用长上下文优化模型同样前缀的请求首 token 仍然慢服务端没有启用前缀缓存查看推理框架日志中 cache hit 指标配置 Prefix Caching接入 SGLang/vLLM 对应功能普通模型推理 library 没有使用显存页管理推理框架实现较基础对比连续批处理和静态批处理的吞吐切换到 vLLM、TensorRT-LLM 等优化框架4096 上下文也能跑但提示 2048 的并发就不行系统预分配的 KV Cache 按最大上下文预留检查服务启动参数中 max-model-len、max-num-seqs按业务实际上下文上限配置不要按最大值预留工程上还有一个常见问题是“KV Cache 一直不释放”。有些推理框架需要手动设置最大缓存大小如果不设置缓存会持续占用显存。排查时可以观察请求结束后显存是否回落如果一直不回落检查框架是否开了显存常驻模式或预分配池以及是否需要调用缓存清理的 API。9. 工程实践建议KV Cache 在原理层面讲清楚之后真正到了部署调优阶段有几条工程建议可以直接落地。第一部署前先估算 KV Cache 显存预算。根据模型层数、KV 头数、目标并发数、目标上下文长度用第 4 节的公式算出 KV Cache 需要多大再决定模型量化等级和最大并发数。不要等 OOM 了再调。第二优先选择支持 PagedAttention 或类似显存管理机制的推理框架。vLLM、TensorRT-LLM、SGLang 在长上下文和并发场景下的显存效率明显优于直接使用原生推理接口。它能让你在同样显存下处理更多请求也能让长上下文任务更稳定。第三尽量让请求有相同前缀。多轮对话系统把 system prompt 放在最前面Agent 应用把工具定义放在最前面API 调用时保持 prompt 模板固定这些都能提高前缀缓存命中率降低首 token 延迟。第四KV Cache 量化可以作为下一步优化手段。把 KV Cache 从 FP16 量化为 INT8 甚至 INT4显存占用直接减半或减到四分之一但需要关注精度损失。建议先在离线评测集上对比量化前后的回答质量再决定是否上线。第五监控要聚焦到 TTFT、TPOT、缓存命中率和显存水位四个指标。这四个指标能覆盖 KV Cache 相关的绝大多数性能问题。日志中建议记录每次请求的序列长度和是否命中前缀缓存方便后续分析成本与性能。10. 小结与下一步KV Cache 是大模型推理性能的核心变量。预填充阶段为历史 token 计算并缓存 K、V解码阶段通过复用缓存避免重复计算这是大模型能高效生成长文本的基础。但缓存的代价是显存随序列长度线性增长由此引出了显存预算、并发控制、前缀缓存和显存管理优化等一整套工程问题。理解 KV Cache相当于拿到了大模型推理性能优化的钥匙。如果你正在做推理部署下一步建议做三件事先用公式估算自己模型的 KV Cache 显存预算再接入支持 PagedAttention 的推理框架对比吞吐最后在业务场景中测试不同前缀长度对缓存命中率的影响。如果你正在准备面试把第 7 节的几个问题用口语表达一遍尤其是显存公式和 PagedAttention 原理基本能覆盖大多数追问。KV Cache 之外下一步值得延伸的方向是系统提示词缓存策略、连续批处理对比实验、以及量化对缓存质量和推理速度的影响。这三块在实际工作里用到的频率非常高建议接着深入。