

在大语言模型的推理过程中,生成文本并非一蹴而就,而是分为多个阶段并涉及多种优化策略。
其中,Prefill(预填充) 和 Decode(解码) 构成了推理的基本流程:前者高效处理用户输入的完整提示(prompt),后者则逐个生成输出 token。而在需要生成多个候选结果时(如提高回复质量或多样性),系统会采用 Parallel Sampling(并行采样) 或 Beam Search(束搜索) 等策略。为了进一步提升效率、避免重复计算,现代推理引擎还引入了 Shared Prefix(共享前缀) 机制,允许多个生成序列复用相同的上下文缓存。
这四个概念共同构成了高效、高吞吐大模型推理的核心基础,也是 vLLM、TGI、TensorRT-LLM 等先进推理系统的关键优化点。
1. Prefill(预填充阶段)#
- 定义:处理用户输入的完整 prompt(提示词)的阶段。
- 输入:完整的 prompt tokens,例如
["Hello", "how", "are", "you", "?"]。 - 计算方式:
- 所有 prompt tokens 一次性并行计算(因为彼此已知,无依赖);
- 生成每个 token 对应的 Key(K)和 Value(V),并缓存到 KV Cache 中;
- 不生成新 token,只“准备上下文”。
- 特点:
- 计算密集(FLOPs 高),但可高度并行;
- 内存带宽压力大(需加载整个模型权重);
- 只发生一次(每个请求开始时)。
✅ 类比:就像阅读一篇文章后记住内容,为后续回答做准备。
2. Decode(解码阶段)#
- 定义:基于 prompt 和已生成的 token,逐个生成新 token 的阶段。
- 输入:当前所有 token(prompt + 已生成部分);
- 计算方式:
- 每次只生成 1 个新 token(自回归);
- 利用 KV Cache 中已有的 K/V,只计算新 token 的 Q,并与历史 K/V 做 attention;
- 新 token 的 K/V 被追加到 KV Cache 中,供下一步使用。
- 特点:
- 无法并行(每个 token 依赖前一个);
- 内存带宽受限(频繁读写 KV Cache);
- 延迟敏感(每步都要等 GPU 计算完);
- 占整个生成过程的大部分时间(尤其长文本)。
✅ 类比:根据记忆逐字回答问题,每说一个词都要回想之前说过什么。
3. Parallel Sampling 与 Beam Search#
这是两种常见的多候选生成策略:
(a) Parallel Sampling(并行采样)#
- 目的:生成多个风格或内容不同的回复,强调多样性(例如聊天机器人提供几种可能的回答)。
- 工作方式:
- 从完全相同的 prompt 出发;
- 同时启动多个彼此独立的生成过程(比如 4 个 sample);
- 每个 sample 在每一步都独立采样下一个 token(通常基于概率分布,如 top-p 或 temperature 控制);
- 因为采样具有随机性,各路径很快就会分叉,生成完全不同后续。
- KV Cache 管理:
- 虽然起始 prompt 相同,但传统实现中每个 sample 维护自己完整的 KV Cache(包括 prompt 部分);
- → 即使前缀相同,也不共享,造成内存冗余;
- (现代引擎可通过 Shared Prefix 优化这一点,见下文)。
- 关键特点:多条“平行宇宙”式的生成轨迹,互不影响。
🌰 举例:输入 “讲个笑话”,并行采样可能输出:
① “为什么程序员…?”
② “有一天,一只鸭子走进酒吧…”
③ “我不会讲笑话,但我知道一个 bug…”
(b) Beam Search(束搜索)#
- 目的:寻找得分最高、最合理的一条输出序列,强调质量与确定性(常用于机器翻译、摘要等任务)。
- 工作方式:
- 维护一个固定大小的候选集,称为 beam(例如 beam width = 4,即始终保留 4 条最佳路径);
- 每一步:对当前所有候选序列分别扩展所有可能的下一个 token,计算整体得分(通常是 log-probability 累加);
- 然后从所有扩展结果中选出总分最高的 4 个,作为下一步的候选;
- 这些候选序列可能共享很长的前缀(比如前 5 个词完全一样,第 6 个才分叉)。
- KV Cache 管理:
- 理论上,所有候选共享相同的 prompt 前缀;
- 如果不优化,会重复存储相同前缀的 K/V,浪费内存;
- 理想实现应支持 Shared Prefix:只存一份公共前缀,各分支仅存差异部分。
- 关键特点:不是完全独立的路径,而是协同竞争、动态剪枝的“精英小队”。
🌰 举例:翻译 “I love you” →
Beam 中可能暂时保留:
① “Je t’aime”(高分)
② “Je vous aime”(稍低分)
③ “J’adore toi”(语法错误,后续会被淘汰)
最终只输出得分最高的完整句子。
4. Shared Prefix(共享前缀)#
- 问题背景:在 Parallel Sampling 或 Beam Search 中,多个生成序列往往共享相同的 prompt 前缀(甚至部分生成前缀)。
- 解决方案:只存储一份公共前缀的 KV Cache,各分支仅存储自己独有的后缀部分。
- 技术实现:
- 使用 树状或图状 KV Cache 结构(如 Radix Tree、Block Manager in vLLM);
- 多个序列通过指针引用同一段 prefix cache;
- 显著降低内存占用(尤其当 beam width 大或 sample 数多时)。
关于vLLM的详细原理讲解,可以参考博客 ↗。
下面从 优点 和 缺点/局限性 两个方面总结 vLLM 的核心特性:
✅ 优点#
| 优势 | 说明 |
|---|---|
| 1. 极高的吞吐量和低延迟 | 得益于 PagedAttention 技术,vLLM 能高效管理 KV Cache 内存,减少内存碎片,吞吐量可达 Hugging Face Transformers 的 10–24 倍。 |
| 2. 支持 Shared Prefix(前缀共享) | 多个请求若具有相同 prompt(如 system prompt),可共享 KV Cache,大幅节省显存,特别适合聊天机器人等场景。 |
| 3. 高效支持连续批处理(Continuous Batching) | 动态合并不同长度的请求进行批处理,避免 Decode 阶段因短请求等待长请求而空转,显著提升 GPU 利用率。 |
| 4. 兼容主流开源模型 | 原生支持 Llama、Llama2/3、Mistral、Qwen、Baichuan、Gemma、Phi 等数十种架构,开箱即用。 |
| 5. 支持多种生成策略 | 包括 greedy search、sampling、beam search、parallel sampling,并支持 logprobs、stop tokens、repetition penalty 等高级功能。 |
| 6. 易于部署和集成 | 提供 OpenAI 兼容的 API 接口,可无缝替换 OpenAI 调用;也支持与 LangChain、LlamaIndex 等框架集成。 |
❌ 缺点 / 局限性#
| 局限 | 说明 |
|---|---|
| 1. 不支持训练或微调 | vLLM 仅用于推理,不能用于 LoRA 微调、QLoRA 或全参数训练(需配合其他框架如 Hugging Face PEFT + DeepSpeed)。 |
| 2. 对超长上下文支持有限 | 虽然支持 RoPE 插值等扩展上下文方法,但 PagedAttention 在极端长序列(如 > 100K tokens)下仍可能面临显存或性能瓶颈。 |
| 3. 内存节省依赖请求模式 | Shared Prefix 和 PagedAttention 的优势在高并发、重复 prompt 场景下最明显;单请求或完全不同的 prompt 下收益较小。 |
| 4. 自定义模型适配需开发工作 | 若使用非主流或自研模型,需手动实现模型加载器和 attention 逻辑,有一定工程门槛。 |
| 5. 暂不支持多模态模型 | 当前主要面向纯文本 LLM,对 LLaVA、Qwen-VL 等多模态模型支持有限(社区正在推进中)。 |
| 6. 资源占用仍高于量化方案 | 虽比原生 HF 高效,但相比 GGUF(llama.cpp) 或 AWQ/GPTQ 量化模型,vLLM 默认运行 FP16/BF16 模型,显存占用更高。 |
📌 总结一句话:#
vLLM 是目前最高效的开源 LLM 推理引擎之一,通过 PagedAttention 和连续批处理等创新,在保持模型精度的同时极大提升了吞吐与资源利用率,特别适合高并发在线服务;但它专注于推理,不替代训练框架,且对硬件资源仍有较高要求。