跳到正文
LEo的网络日志
返回

llm 推理服务为什么需要多级缓存、pd 分离和连续批处理

现在很多 ai 平台都会提供类似这样的能力:

在 gpu 服务器上搭建 llm api,通过多级缓存、pd 分离、连续批处理等技术实现降本增效。

第一次看到这句话,容易感觉每个词都认识,但连起来不知道到底在做什么。

用一句白话概括:

把大模型部署成 api,然后让昂贵的 gpu 少做重复工作、减少空闲、合理分工,用同样的硬件处理更多请求。

这篇文章不讨论复杂的数学原理,只从实际工程场景出发,理解这三种技术分别解决什么问题。

模型能提供 api,只是第一步

假设一台 gpu 服务器上部署了 qwen,并通过 vllm、sglang 或 tensorrt-llm 对外提供接口:

POST /v1/chat/completions

请求流程并不复杂:

用户请求

llm api

gpu 推理

返回结果

到这里已经完成了最基本的模型服务化,但模型能跑起来,不代表服务适合生产环境。

用户增多以后,真正的问题变成了:

如何让同样数量的 gpu 处理更多请求,同时控制首个 token 延迟和后续生成速度?

如果没有做好推理优化,gpu 时间可能消耗在重复计算、等待其他请求、显存碎片以及不同计算阶段的相互干扰上。多级缓存、pd 分离和连续批处理,就是从不同方向减少这些浪费。

多级缓存:算过的内容尽量不要重算

假设企业智能助手的每个请求都带着一段很长的 system prompt:

你是公司的 ai 助手。
只能根据内部知识库回答问题。
回答必须准确、简洁……

用户的问题不同,但前面的系统指令、知识库上下文或多轮对话前缀可能完全相同。如果每个请求都从头计算一遍,会浪费大量 gpu 算力。

缓存的核心不是简单地“存数据”,而是:

保存已经完成的计算或结果,在满足复用条件时避免重复计算。

推理服务里常见的缓存并不只有一种:

缓存保存什么适合的场景
结果缓存完整请求对应的回答输入完全相同、结果允许复用
prefix cache公共前缀对应的 kv 状态system prompt、固定模板或公共上下文相同
kv cache当前序列已经计算过的注意力状态生成下一个 token 时复用历史上下文

例如两个请求都以同一段系统指令开头,prefix cache 命中后,后一个请求可以从已计算的公共前缀继续,而不是重新处理整段内容。

整个过程可以理解为:

缓存命中

减少重复计算

降低 gpu 工作量

提高吞吐量并降低单次请求成本

缓存也不是免费的。它会占用内存或显存,还需要处理淘汰、隔离和一致性问题。如果请求之间没有可复用内容,缓存命中率很低,收益也会随之下降。

pd 分离:把“读题”和“答题”分开

大模型推理可以粗略分成两个阶段:

阶段白话解释典型特点
prefill读题一次处理大量输入 token,计算密集
decode答题逐步生成 token,频繁读取 kv cache

假设用户提交了一篇很长的技术文档,让模型进行总结。模型首先需要处理整段输入,这就是 prefill;完成以后,再一个 token 一个 token 地生成回答,这就是 decode。

两个阶段的计算特点不同。把它们混合运行在同一组 gpu 上,长 prompt 的 prefill 可能影响正在进行的 decode,导致其他用户等待下一个 token 的时间变长。

pd 分离的做法,是让不同的资源分别负责 prefill 和 decode:

                 用户请求

                  调度器

          ┌─────────┴─────────┐
          ↓                   ↓
    prefill 实例          decode 实例
       读题                   答题
          └────传递 kv 状态────→

可以把它想象成饭店里的分工:备菜组负责洗菜、切菜,炒菜组负责烹饪。两类工作可以独立调度、扩容和优化。

例如平台主要处理 rag、长文档和长 prompt,可以增加 prefill 资源;如果主要生成代码、报告等长回答,则可以重点调整 decode 资源。

不过,pd 分离并不是把 gpu 分成两组就一定更快。prefill 产生的 kv 状态需要传给 decode 实例,这会增加网络传输和调度开销。请求规模较小、输入较短,或者网络条件不合适时,分离后的收益可能抵不过额外成本。

连续批处理:有空位就接收新请求

gpu 擅长并行计算,因此推理框架通常会把多个请求组成一个 batch。但用户生成的内容长短不同:

用户 a:生成 100 个 token
用户 b:生成 500 个 token
用户 c:生成 1000 个 token

如果必须等整个 batch 全部结束后才能接收下一批请求,那么 a 和 b 完成以后,对应的计算位置会一直空着,直到 c 也完成。

连续批处理会在每轮生成过程中动态调整 batch:

时间 →

a a a 完
      d d d d d

b b b b 完
        e e e e e

c c c c c c c c c

谁先完成,就尽快把等待中的新请求补进来,不必等同一批里的所有请求结束。

这很像医院叫号:一个人看完以后马上叫下一位,而不是等当前这一组人全部看完再叫下一组。它的目标是减少 gpu 空转,让计算资源持续处理有效请求。

连续批处理提高吞吐量的同时,也需要调度器控制 batch 大小、显存占用和请求优先级。塞入太多请求可能增加单个请求的延迟,所以生产环境通常需要在吞吐量和延迟之间做取舍。

三种技术解决的是三类浪费

把它们放在一起看,会更容易理解:

技术主要解决的问题白话理解
多级缓存重复计算算过的尽量不要再算
pd 分离prefill 和 decode 相互干扰读题和答题分开处理
连续批处理batch 中途出现空闲有空位就安排新请求

组合后的推理链路可以粗略表示为:

用户请求

api gateway / router

缓存检查
  ├─ 命中 → 复用结果或计算状态
  └─ 未命中

    prefill 实例

    kv 状态传输

    decode 实例

    连续批处理

    返回结果

实际生产环境还会涉及模型并行、量化、推测解码、显存管理、限流、监控和自动扩缩容等问题,但刚开始学习 llm 推理时,可以先记住这三个方向:

少做重复工作
+
让不同阶段合理分工
+
减少计算资源空闲

对 ai 平台意味着什么

如果一个 ai 平台只能完成:

选择模型

分配 gpu

启动 pod

暴露 api

它解决的是“模型如何运行并提供服务”。真正面向生产的推理平台,还需要继续回答这些问题:

因此,平台能力通常是逐步演进的:

模型能够运行

模型能够提供 api

多人并发调用

gpu 高效利用

生产级推理服务

多级缓存、pd 分离和连续批处理,正是从“模型能提供 api”走向“高性能推理服务”过程中很典型的三种技术。

总结

以后再看到“通过多级缓存、pd 分离和连续批处理实现降本增效”,可以直接翻译成:

让 gpu 少做重复工作,让读题和答题按各自特点分工,并在有可用资源时尽快接收新请求。

最终目标只有一个:

用同样数量的 gpu,稳定地服务更多请求,降低每次推理的平均成本。



上一篇
chatgpt小贴士(十)
下一篇
零基础看懂 slurm:从多节点集群到第一个作业