推理优化的第一性原理:Prefill 和 Decode 是两种完全不同的工作负载
同样一个开源模型、同样的显卡,不同团队的推理成本可以相差三到十倍。这个差距的来源不是黑科技,而是对推理过程两个阶段的理解深度。
一次推理请求分成 Prefill 和 Decode。Prefill 处理用户输入的全部 Prompt,一次性并行计算所有 Token 的表示,生成第一个输出 Token 和整段 KV Cache。Decode 逐个 Token 往外蹦,每生成一个 Token 都要对之前全部历史做一遍注意力计算。
这两个阶段的资源画像完全相反。Prefill 是计算密集的,输入全长并行,能吃满算力,用户感知的是首字延迟(TTFT)。Decode 是访存密集的,逐 Token 串行,每生成一个 Token 都要把全部模型权重和整段 KV Cache 从显存搬到计算单元,搬一次只算一个 Token。显存带宽而不是算力,才是 Decode 的真正天花板。
理解了这一点,所有优化技术的动机就都清楚了:要么少搬数据,要么一趟多搬几封信,要么把两种性格的工作分开安排。
KV Cache 是 Decode 慢的一大根源。每个 Token 的 KV Cache 大小等于 2 × 层数 × KV 头数 × 每头维度 × 每元素字节数。一个 7B 模型在 FP16 下,每 Token 的 KV Cache 大约是 512 KB。长上下文加上高并发,KV Cache 会迅速吃掉显存,限制能同时服务的序列数。PagedAttention 的做法是把 KV Cache 切成固定大小的块,按需分配非连续显存,消除预留连续空间造成的碎片;前缀复用则让共享相同 system prompt 或检索文档的请求直接跳过重复的 prefill。
Continuous Batching 解决的是“批处理粒度”问题。传统静态批处理要等一个 batch 全部生成完才能接下一批,短请求被长请求拖住。连续批处理在迭代级别调度,一个序列生成完就可以退出,新请求可以立刻加入。吞吐提升的来源不是“算得更快”,而是“GPU 没有空等”。
投机解码是另一个维度的思路:用一个小模型快速生成若干草稿 Token,大模型一次性验证,接受的部分直接保留。它的收益取决于草稿的接受率,接受率高时等效于“一趟多送了几封信”。但草稿模型本身也有成本,接受率低时反而拖慢。
PD 分离则是把 Prefill 和 Decode 放到不同的资源池上,因为它们的瓶颈完全不同。计算密集的 Prefill 用高算力配置,访存密集的 Decode 用高带宽配置,避免两种工作负载互相干扰。
一个务实的优化顺序是:先确认瓶颈在 Prefill 还是 Decode,再看 KV Cache 的显存占用和命中情况,然后评估 Continuous Batching 是否已经开启并合理配置,最后才考虑量化和投机解码。顺序反了,容易在错误的环节投入精力。推理优化不是“把所有技术叠上去”,而是“先搞清楚钱花在哪个阶段”。
- 点赞
- 收藏
- 关注作者
评论(0)