共计 2676 个字符,预计需要花费 7 分钟才能阅读完成。
前言:一个延迟问题的启示
2025年,我们调用的绝大多数大模型(从GPT-4o到Claude 3.5到开源LLaMA-3)都采用了高效的推理策略。但如果你曾深入观察过模型的实际响应,会发现一个有趣的现象:模型生成第一个token往往比后续token慢很多。这让我想起2024年底帮团队优化一个实时对话系统时,用户抱怨“打字间歇感”太强——每句话的首字延迟接近1秒,而后续流畅度却很高。这个问题的根源不在于模型本身,而在于一个关键的工程化原理:KV Cache。今天这篇文章,我想从这两个核心技术入手,聊聊大模型是如何在不降低效果的前提下加速的。
KV Cache:为什么第一个token那么慢?
如果你了解Transformer的自注意力机制,应该知道它的计算复杂度与序列长度的平方成正比。但实际推理时,我们用的是自回归生成:每一步只预测下一个token,然后把当前token拼接到已生成的序列后面。乍一看,每步都要重新计算所有历史token的注意力,这显然不合理。
简单计算一下:假设输入序列长度是L,当前已生成到第t步。标准的注意力计算需要对所有L+t个token进行query、key、value的矩阵乘。而实际上,每一步新增的只有最后一个token的query,其他位置的query计算结果完全一样。我们却重复计算了历史token的key和value —— 这就是瓶颈。
KV Cache正是为了解决这个问题:在每一步生成时,将前面所有token的Key矩阵和Value矩阵缓存下来。后续步骤只需计算新token的Key/Value,然后追加到缓存中。这样一来,计算量从O((L+t)^2)降低到O((L+t)·d),其中d是token维度。这个优化直接让解码阶段的吞吐量提升5-10倍。但你注意到了吗?在第一步生成第一个token时,KV Cache为空,模型不得不先计算所有输入token的K和V来填充缓存 —— 这解释了首token延迟。
当然,KV Cache也有代价:显存占用随长度线性增长。2025年流行的推理框架(如vLLM、TGI)都实现了PagedAttention(分页注意力)来管理缓存碎片,这又是一个值得深挖的工程优化。对于有经验的读者,我建议在阅读这些框架源码时,重点关注其KV Cache的预分配与共享策略——这往往决定了长上下文场景下的吞吐极限。
Speculative Decoding:用“小模型”为“大模型”开路
KV Cache解决了计算冗余,但大模型每步的矩阵乘依然耗时。有没有办法在一次前向传播中生成多个token?直观上似乎不可能,因为自回归生成是串行的,下一个token依赖前一个。但在2024-2025年,Speculative Decoding(推测解码) 逐渐从研究走向工程主流,成为GPT-4 API和高性能推理服务的标配。
它的核心思想很聪明:用一个轻量级的小模型(draft model)先快速生成一个候选序列,再用大模型一次性验证这些token是否合格。如果小模型推测的token全部被大模型接受,那一次大模型前向传播就相当于生成了多个token。即使部分被拒绝,效率损失也远小于纯自回归。
具体流程可以拆解为三步:
- 采样阶段:小模型(例如一个小的LLaMA-2-1B)自回归生成N个token候选序列。
- 验证阶段:大模型计算整个候选序列的联合概率,利用拒绝采样(Rejection Sampling)的数学保证,只保留那些概率分布与大模型自身分布一致的token。
- 接受/回退:如果某个token被拒绝,回退到该位置并重新用小模型生成,但大模型已经计算了该位置的概率分布,可以直接复用。
这里的关键数学事实是:拒绝采样保证了最终输出的分布与大模型直接采样完全一致,没有任何质量损失。这是一个无损优化。
实际应用中,小模型与大模型的粒度差异性很关键。比如2025年Google的Medusa框架采用多个预测头一次性预测多个后续token,本质上是将小模型嵌入到大模型内部。而DeepMind的Lookahead Decoding则通过并行验证多个路径,进一步降低了回退概率。
需要注意的是,Speculative Decoding的加速比依赖于小模型的猜测命中率。如果小模型太简单(比如bfloat16量化到8bit的小模型),猜测准确性就低,可能频繁回退,导致大模型白白计算了候选序列但只采纳了一个token。实践中,我们通常选择与大模型同源、但参数量小一个数量级的模型作为draft,比如用LLaMA-3-8B配合LLaMA-3-70B。
反思:为什么这些技术不是万能的?
KV Cache和Speculative Decoding虽然强大,但都有应用边界。对于Prompt-phase(输入阶段),KV Cache无法生效——因为输入tokens本身就需要全量计算。这导致在零样本短输入场景下,KV Cache的收益有限;而在长上下文(如32K tokens)的场景下,显存会成为新瓶颈,开源框架的PagedAttention变得不可或缺。
另一个容易被忽视的问题是:Speculative Decoding在batch推理时加速比会下降。因为小模型在多个请求上并行生成候选序列,但大模型验证时需要对所有请求的候选序列做batch验证——如果各请求的候选长度不一致,需要进行padding操作,从而引入额外计算。这也是为什么Meta的Scaling Speculative Decoding研究(2025年初)集中在如何对齐batch内各请求的预测步长。
总结:从原理到工程实践的启示
回顾这两个技术,它们的共同点是:不改变模型参数,而是利用推理过程中的结构冗余和概率冗余来优化计算。对于深度学习工程师而言,理解这些底层原理的意义在于:当你在2026年面对一个千亿参数模型的实时部署时,你不再只依赖黑盒框架的“加速开关”,而是能准确诊断是KV Cache的显存瓶颈还是Speculative Decoding的batch效率问题。
随手提一个小经验:如果你在推理日志中看到首token延迟远高于其他token,且显存占用不高,那么首要优化方向是Prompt caching(缓存常见输入前缀的KV Cache),这比换用更快的矩阵乘法库更立竿见影。而如果你发现模型生成长句子时越到后面越快,那多半是KV Cache的功劳,别急着降精度量化。
希望这篇技术笔记能帮你从“会调API”进阶到“懂优化原理”。下一次别人抱怨大模型推理慢时,你能笑着反问一句:你检查过KV Cache的预分配策略了吗?