核心摘要
大语言模型 (LLM) 推理是将输入文本(Prompt)转化为输出结果的过程。它的核心工作流分为两个阶段:高度并行计算的 Prefill 阶段(处理 Prompt)与串行生成的 Decode 阶段(逐字生成)。在这个过程中,KV Cache 技术是优化显存读取和加速解码的关键。
📋 目录
- 什么是 LLM 推理?
- LLM 推理是如何工作的?双阶段解析
- 深入理解 KV Cache 原理
- 核心性能指标:TTFT 与 TPOT
- LLM 推理实战指南
- 最佳实践:如何优化推理性能
- 常见问题 (FAQ)
- 总结
✨ 核心要点
- 自回归生成 (Autoregressive):LLM 每次只生成一个 Token,并使用之前生成的所有 Token 作为下一次生成的上下文。
- 两阶段执行:推理过程被拆分为“算力瓶颈”的 Prefill 阶段和“显存带宽瓶颈”的 Decode 阶段。
- KV Cache 的重要性:缓存历史的 Key 和 Value 矩阵减少了算力消耗,但极大增加了显存(VRAM)占用。
- 指标优化:优化 TTFT 能提升用户体验(觉得模型反应快),优化 TPOT 则决定了文本输出的速度。
💡 工具推荐:使用 Token 计数器 — 快速计算你的 Prompt 消耗了多少 Token,从而预估大模型推理成本和延迟。
什么是 LLM 推理?
LLM 推理(Inference)是指经过训练的大语言模型接收输入文本(Prompt)并预测最可能的后续文本的过程。与通过海量数据更新模型权重的训练阶段不同,推理阶段使用的是固定的(冻结的)权重进行前向传播计算。
现代 LLM(如 GPT-4、Llama 3 和 DeepSeek)均采用自回归 (Autoregressive) 机制运行。这意味着模型在预测下一个 Token 时,必须依赖所有已知的历史 Token。新生成的 Token 会被追加到序列末尾,整个过程不断循环,直到模型输出一个停止标记(如 <EOS> Token)为止。
📝 术语链接:Token — 大语言模型处理数据的最小基本单位,它可以是一个词、一个词根或单个字符。
LLM 推理是如何工作的?双阶段解析
基于 Transformer 架构的大模型,其推理过程被明确划分为两个阶段:Prefill(预填充)和 Decode(解码)。
1. Prefill 阶段(处理 Prompt)
当你向大模型发送一段 Prompt 时,模型首先进入 Prefill 阶段。在此阶段,模型会并行处理整个输入序列。
由于所有的输入 Token 都是已知的,GPU 可以充分利用高度优化的矩阵乘法(GEMM)进行大规模并发计算。Prefill 阶段的核心目标是:
- 计算输入 Prompt 中所有 Token 的注意力分数(Attention Scores)。
- 初始化并填充 KV Cache。
- 生成输出序列的第一个 Token。
该阶段通常是算力瓶颈 (Compute-bound),意味着它的处理速度主要受限于 GPU 的原始浮点运算能力(FLOPs)。
2. Decode 阶段(生成 Token)
当第一个 Token 生成后,模型就进入了 Decode 阶段。在这个阶段,模型开始逐个生成后续的 Token。
对于每一个新 Token,模型都需要关注(Attend)所有之前生成过的历史 Token。因为这个过程是串行的(必须等上一个字生成完毕,才能生成下一个字),GPU 无法像 Prefill 阶段那样在序列维度上进行并行计算,而是依赖于矩阵-向量乘法(GEMV)。
Decode 阶段是显存带宽瓶颈 (Memory-bandwidth bound)。GPU 将绝大部分时间花在把模型权重和 KV Cache 数据从显存(HBM)搬运到计算核心上。
深入理解 KV Cache 原理
在生成下一个 Token 时,注意力机制(Attention)需要用到所有历史 Token 的 Key (K) 和 Value (V) 矩阵。如果每次生成新词都把整句话从头算一遍,计算量将呈二次方级增长($O(N^2)$),这在处理长文本时是不可接受的。
KV Cache 通过将历史 Token 的 K 和 V 张量缓存在 GPU 显存中解决了这个问题。
- 不使用 KV Cache:每走一步都要重新计算所有历史数据的 $K$ 和 $V$。
- 使用 KV Cache:模型只需计算最新生成的那个 Token 的 $K$ 和 $V$,将它们追加到缓存中,然后利用缓存的历史数据进行注意力计算。
虽然 KV Cache 大幅减少了计算量,但它消耗了海量的显存。对于 100k Token 的长上下文,仅 KV Cache 本身就可能占用数十 GB 的显存。这也是为什么像 vLLM 中的 PagedAttention(分页注意力)技术对于高并发推理服务器如此关键的原因。
核心性能指标:TTFT 与 TPOT
在评估 LLM 推理引擎(如 vLLM、TGI)时,业界通常关注两个核心延迟指标:
| 指标 | 全称 | 定义 | 对用户的影响 |
|---|---|---|---|
| TTFT | Time To First Token (首 Token 延迟) | 从发送请求到接收到模型生成的第一个 Token 的耗时。 | 决定了 AI 的“响应速度”。TTFT 过高会让用户觉得系统卡顿。 |
| TPOT | Time Per Output Token (输出每个 Token 耗时) | 在 Decode 阶段,平均生成每一个后续 Token 所需的时间。 | 决定了用户的“阅读速度”。如果 TPOT 是 50ms,意味着模型每秒生成 20 个 Token。 |
LLM 推理实战指南
下面我们用伪代码展示大模型自回归推理在底层是如何工作的:
import torch
def generate_text(model, tokenizer, prompt, max_tokens=50):
# 分词:将输入文本转为 input_ids
input_ids = tokenizer.encode(prompt, return_tensors="pt")
# 初始化 KV Cache
past_key_values = None
generated_tokens = []
for _ in range(max_tokens):
# 执行前向传播
with torch.no_grad():
outputs = model(
input_ids=input_ids,
past_key_values=past_key_values, # 传入历史缓存
use_cache=True # 启用 KV Cache
)
# 获取最新预测的 Token(这里使用贪心解码 argmax)
next_token_logits = outputs.logits[:, -1, :]
next_token = torch.argmax(next_token_logits, dim=-1)
# 追加到生成结果列表中
generated_tokens.append(next_token.item())
# 更新下一次迭代所需的 KV Cache
past_key_values = outputs.past_key_values
# 下一轮的输入仅仅是刚才生成的这一个 Token
input_ids = next_token.unsqueeze(0)
# 停止条件判断
if next_token.item() == tokenizer.eos_token_id:
break
return tokenizer.decode(generated_tokens)
🔧 立即体验:使用我们的免费 JSON 格式化工具 在线解析、美化和验证各大模型 API 返回的 JSON 响应数据。
最佳实践:如何优化推理性能
- 使用 PagedAttention 框架:直接使用 vLLM 等成熟的推理框架。它们通过 PagedAttention 动态管理 KV Cache 显存,消除了内存碎片,将吞吐量(Batch Size)提升了高达 5 倍。
- 应用模型量化 (Quantization):将模型权重从 FP16 降低到 INT8 或 INT4(如使用 AWQ 或 GPTQ 格式)。这不仅降低了显存需求,还极大缓解了 Decode 阶段的显存带宽瓶颈。
- 开启连续批处理 (Continuous Batching):不要等待一个 Batch 中所有请求都完成才开始下一轮。只要有请求生成完毕,立刻将新请求插入到 Batch 中,最大化 GPU 利用率。
- 控制 Prompt 长度:因为 Prefill 阶段的计算量与 Prompt 长度的平方成正比,保持上下文精简能有效降低 TTFT 和算力成本。
⚠️ 常见错误:
- 忽视 KV Cache 的显存占用 → 正确做法:在部署前务必计算最大并发数下的 KV Cache 大小。生成过程中的 OOM(显存溢出)报错,90% 都是因为 KV Cache 爆满,而非模型权重太大。
- 在生产环境使用原生的 Hugging Face
pipeline→ 正确做法:原生管道未经过深度优化,在生产环境中应该使用 vLLM、TGI 或 TensorRT-LLM 等企业级推理服务器。
常见问题 (FAQ)
Q1:为什么生成的文本越长,大模型回复的速度就越慢?
随着生成序列的增长,KV Cache 的体积也在不断膨胀。在 Decode 阶段,GPU 为了生成单个 Token,必须将整个庞大的 KV Cache 从显存读取到计算核心。这种显存带宽瓶颈导致了随着上下文变长,生成速度(TPOT)会出现轻微的衰减。
Q2:什么是连续批处理 (Continuous Batching/In-flight Batching)?
传统的静态批处理必须等待 Batch 中最长的那句话生成完毕,才能整体处理下一个 Batch。而连续批处理能在 Token 级别动态地将新请求加入到当前 Batch,并剔除已完成的请求,从而极大地提升了并发吞吐量。
Q3:投机解码 (Speculative Decoding) 是如何加速推理的?
投机解码使用一个参数量极小的“草稿模型”快速猜测未来几个 Token,然后交由主模型在一次并行计算(Prefill 方式)中验证。这种做法将“受限于显存带宽”的逐字解码,转化为了“受限于算力”的并行验证,从而在不改变 KV Cache 结构的前提下显著提升了推理速度。
总结
LLM 推理是一场算力与显存带宽之间的精妙平衡。通过深入理解并行的 Prefill 阶段和串行的 Decode 阶段之间的区别,并利用 KV Cache 与 PagedAttention 等优化技术,开发者可以大幅降低大模型的延迟和部署成本。
👉 探索 QubitTool 开发者工具箱 — 使用我们提供的全套免费工具,加速您的 AI 研发工作流。