LLM 推理技术详解:标准机制与工业级优化
版本: 2.0 (修订版) 核心修订: 明确区分了"KV Cache 的标准推理逻辑"与"工业级系统优化"。
1. 核心机制:KV Cache 标准推理流程
只要开启了 KV Cache(这是所 有现代推理引擎的默认基准),LLM 的推理过程就严格包含两个截然不同的阶段:Prefill(预填充) 和 Decode(解码)。
这是算法层面的标准行为,旨在消除重复计算。
第一阶段:Prefill (预填充 / 首词生成)
"一口气读完 Prompt,并生成第一个词"
- 输入 (Input): 完整的提示词序列
[Token_0, Token_1, ..., Token_N-1]。 - 计算行为:
- 全量计算: 这是一个巨大的矩阵乘法。模型并行计算所有 Token 的 。
- 填充 Cache: 将计算出的所有 和 存入显存。
- 首词预测: 利用最后一个 Token 的输出,预测生成
Token_N。
- 算力特征: 计算密集型 (Compute-bound)。GPU 利用率极高,因为是一次性并行处理矩阵。
第二阶段:Decode (解码 / 自回归生成)
"只进一个词,只算一次注意力"
- 输入 (Input): 仅仅是 上一步生成的最新 Token
[Token_N](Shape:1 × Dim)。- 注意:这里绝对不会再输入之前的 Prompt。
- 计算行为:
- 算当前: 计算这 1 个 Token 的 。
- 取历史: 从显存中取出之前存好的 。
- 拼整体: 。
- 算 Attention:
- 使用 (1个向量) 去查询 (N+1个向量)。
- 运算本质是 向量-矩阵乘法 (GEMV),而不是矩阵-矩阵乘法 (GEMM)。
- 算力特征: 访存密集型 (Memory-bound)。
- 计算量非常小(只算一个词)。
- 瓶颈在于显存带宽:需要把巨大的 从显存搬运到计算核心,仅为了和这 1 个向量做乘法。
2. 为什么说这是"标准"而非"进阶"?
如下表所示,只要不是教学用的 Demo 代码,生产环境下的推理必须遵循上述逻辑。
| 模式 | 输入数据形状 (Step N) | Q 的计算量 | 是否可用 |
|---|---|---|---|
| 朴素模式 (NanoGPT) | [0 ... N] (全量) | 计算 个 Q | ❌ 不可用 (速度 ,慢且贵) |
| 标准 KV 模式 (HuggingFace) | [N] (仅当前词) | 计算 1 个 Q | ✅ 基准线 (速度 ,业界标准) |
3. 总结对比图
| 维度 | NanoGPT (教学) | 标准推理 (Baseline) |
|---|---|---|
| 核心逻辑 | 每次重算全文 | Prefill + Decode |
| Input 形状 | 变长 [0...t] | 恒定 [1] |
| KV Cache | 无 | 有 (连续显存) |
| 瓶颈 | 计算量爆炸 | 显存碎片 / 带宽瓶颈 |
| 代表库 | minGPT | transformers |
4. 标准 KV Cache 的局限性
虽然 KV Cache 解决了重复计算问题,但传统实现(如 HuggingFace Transformers)存在严重的显存管理问题:
4.1 预分配浪费
假设模型的 max_len = 2048,当用户输入"你好"(2 个 Token)时:
- 系统必须预留 2048 个 Token 的连续显存空间
- 实际只用了几个 Token,剩余空间被锁定但空置
- 浪费率高达 60% - 80%
4.2 显存碎片化
- 内部碎片: 预留了没用完的空间
- 外部碎片: 显存总量够,但因不连续无法分配给新请求
4.3 并发受限
由于每个请求都要预留大块连续显存,同一张显卡能同时服务的请求数(Batch Size)被严重限制。
如何解决这些问题?
vLLM 团队提出的 PagedAttention 技术,借鉴操作系统虚拟内存分页思想,将 KV Cache 切分为小块按需分配,彻底解决了显存碎片化问题。
👉 详见:PagedAttention:vLLM 的显存管理革命
一句话总结: Prefill 和 Decode 是 KV Cache 的物理定律(基本逻辑)