← articles

LLM 推理:从 Prefill 到 Decode

从推理引擎视角理解模型计算、KV Cache、请求调度与性能指标。

llminferencetransformerinternals

一、建立推理引擎的全局视图

1. 一次请求的生命周期与核心指标

从请求进入到生成结束:Prefill 与 Decode 的分工

沿着一个请求说明 Prefill 如何处理已知输入、Decode 如何复用状态逐步生成,直到满足结束条件。

TTFT、ITL 与输出吞吐:引擎要优化什么

用首 Token 等待时间、后续 Token 间隔和整体输出速率,说明推理引擎需要平衡的体验与处理能力。

2. Vocabulary、Chat Template 与 Tokenization

Vocabulary:Token、ID 与词表空间

说明词表如何定义 Token 与整数 ID 的对应关系,并决定输入 Embedding 和输出 Logits 的词表维度。

Chat Template:把消息组织成模型输入

说明 Chat Template 如何按模型约定排列角色、消息内容与控制标记,形成待编码的输入。

Tokenization:从文本到 Token IDs

说明 Tokenizer 如何使用配套词表和编码规则,把格式化文本转换成模型可接收的 ID 序列。

3. 请求状态、Scheduler 与 KV Cache

模型配置、张量维度与请求状态

明确模型的层数、隐藏维度和 Head 配置,并说明引擎如何记录每个请求的长度、进度和生成参数。

Scheduler:调度队列与 Token Budget

说明调度器如何结合待处理 Token 数、显存容量与请求状态,选择本轮执行的工作。

KV Cache:每层状态存在哪里

说明引擎如何按层保存已处理位置的 Key 和 Value,并维护请求与这些缓存状态的对应关系。

二、Prefill:把 Prompt 变成可复用的状态

4. 输入张量、位置与 Embedding

Token IDs、位置编号与输入长度

说明引擎如何组织本轮 Token IDs、位置编号和有效长度,使模型正确识别每个待计算位置。

Embedding:从整数索引到隐藏状态

说明 Embedding 如何按 Token ID 查表,将离散索引转换成后续计算使用的隐藏向量。

5. 穿过一个 Transformer Block

残差流与 Block 的计算全貌

展示隐藏状态如何沿残差主路前进,并接收 Attention 与 MLP 两条分支产生的更新。

RMSNorm:归一化 Attention 分支输入

说明 RMSNorm 如何逐位置调整隐藏向量的数值尺度,为 Attention 分支的投影计算准备输入。

Q/K/V Projection 与 GQA

说明线性投影如何产生 Q、K、V,以及 GQA 如何让多个 Query Heads 共享 KV Heads。

可选变体:QK Norm

说明采用 QK Norm 的模型如何在注意力打分前归一化 Q/K,调整点积的输入尺度。

RoPE:将位置注入 Q/K

说明 RoPE 如何按位置旋转 Q/K 的坐标,使注意力点积包含相对位置信息。

长上下文扩展:YaRN

说明 YaRN 如何调整 RoPE 的频率与注意力尺度,帮助模型适应更长的上下文。

Core Attention:打分、Mask、Softmax 与 Value 聚合

说明 Query 如何与 Key 打分、通过 Mask 限制可见位置,再用 Softmax 权重聚合 Value。

可选变体:Soft Capping 与局部注意力

说明 Soft Capping 如何平滑限制分数幅度,以及局部注意力如何缩小各位置可直接访问的上下文范围。

合并 Heads、Output Projection 与第一次 Residual Add

说明多个 Head 的结果如何合并、投影回隐藏维度,并与 Attention 分支入口的残差相加。

RMSNorm、SwiGLU 与第二次 Residual Add

说明隐藏状态如何经过归一化和 SwiGLU 门控变换,再将 MLP 输出加回残差主路。

6. 穿过全部层,保存各层 KV

各层独立参数与隐藏状态更新

说明各层如何使用自己的参数重复执行 Block,逐层更新同一序列各位置的表示。

每层 K/V 的写入与因果依赖

说明各层生成的 K/V 如何保存,以及因果依赖为何允许这些状态在后续生成中复用。

7. Final Norm、LM Head 与第一个输出 Token

最后有效位置的 Hidden State

说明常规下一 Token 生成为何使用完整 Prompt 最后一个有效位置的状态进行预测。

Final RMSNorm 与 Vocabulary Logits

说明最终隐藏状态如何经过归一化和输出投影,形成覆盖整个词表的候选分数。

Logits 处理、Vocabulary Softmax 与首次采样

说明生成策略如何处理候选分数、构造采样分布或执行贪心选择,得到第一个输出 Token。

8. Prefix Cache 与 Chunked Prefill

Prefix Cache 命中后还需要计算什么

说明引擎如何复用相容前缀的 K/V,并为尚未缓存的输入及所需输出状态安排计算。

Chunked Prefill:分块执行与阶段衔接

说明长 Prompt 如何拆成多个计算块,并在块间延续 KV 状态直到具备首次生成所需的上下文。

排队、缓存命中与分块调度如何影响 TTFT

说明首次输出前的等待时间如何受到调度排队、实际新增计算量和分块执行安排的共同影响。

三、Decode:复用状态,逐步生成

9. 一个新 Token 如何再次经过模型

从已采样 Token 开始下一轮前向计算

说明刚选出的 Token 如何作为新输入进入模型,并产生用于预测再下一个 Token 的状态。

Prefill 与 Decode 的输入形状对比

对比 Prefill 每序列处理多个新位置与常规 Decode 每序列处理一个新位置时的张量形状。

复用完整模型路径:Embedding 到 LM Head

说明 Decode 仍会执行 Embedding、全部 Transformer Blocks、最终归一化和输出投影。

10. 单位置 Attention 与 KV Cache 增长

当前位置的 Q/K/V 与 RoPE

说明每轮 Decode 如何只为当前新位置生成 Q/K/V,并使用该位置编号执行 RoPE。

当前 Query 如何读取历史与当前 K/V

说明当前 Query 如何访问本层允许读取的历史与当前 K/V,得到上下文相关的注意力输出。

当前 K/V 何时写入缓存

说明新 Token 经过各层计算后才产生相应 K/V,以及这些状态如何成为后续步骤的缓存。

上下文增长与 Decode 每步成本

说明全注意力下历史长度增长如何增加 KV 存储与读取需求,并影响单步执行成本。

11. 采样、停止条件与增量输出

从 Logits 选择下一个 Token

说明每轮如何按生成参数和约束处理 Logits,选择下一项输出 ID。

EOS、长度限制与停止序列

说明引擎如何根据结束 Token、输出长度和停止序列判断请求是否应继续生成。

Detokenization 与流式输出边界

说明输出 ID 如何增量还原为文本,以及 Token 生成、文本事件和网络交付的边界为何可能不同。

自回归循环与 ITL

说明前一轮选择如何决定下一轮输入,以及计算与调度等待如何共同形成 Token 间隔。

四、引擎如何同时服务多个请求

12. Continuous Batching 与阶段间调度

每轮重新组织活跃请求

说明引擎如何在迭代边界移除已完成请求、接纳可执行工作,并重新组成计算批次。

Prefill 与 Decode 如何共享执行机会

说明调度器如何为待处理 Prompt 和正在生成的序列安排资源,管理两类工作之间的干扰。

Token Budget、吞吐与尾延迟的权衡

说明每轮允许执行的 Token 数如何影响批量大小,并在整体吞吐和请求尾延迟之间形成取舍。

13. Paged KV Cache、容量压力与资源回收

逻辑位置、物理块与前缀共享

说明每个请求的逻辑 KV 位置如何映射到物理块,以及相容前缀如何通过共享块复用状态。

KV Cache Utilization:容量压力如何显现

说明 KV 使用比例如何反映缓存池容量压力,并结合活跃请求和可回收块判断可用空间。

等待、抢占与重算

说明 KV 容量不足时引擎如何延迟接纳、暂停请求或重新计算状态,以及这些选择的代价。

请求完成、取消与资源回收

说明请求结束或取消后如何退出调度、释放缓存引用,并按缓存策略回收或保留可复用块。

五、把整条链路串起来

14. 用时间线理解延迟、吞吐与 Goodput

一次请求:进入队列、Prefill、Decode 与结束

把输入准备、排队、首次输出、后续生成与资源回收串成一条可追踪的请求时间线。

TTFT 与 ITL:测量边界、平均值与尾延迟

明确首 Token 延迟与相邻 Token 间隔的计时边界,并用分位数揭示平均值隐藏的等待和卡顿。

Output Throughput:聚合吞吐与单请求速度

区分单位时间内所有请求的输出总量与单个请求的生成速度,说明两者为何可能向不同方向变化。

Goodput:请求级达标规则与有效吞吐

先定义每个请求的延迟达标条件,再统计单位时间内达标的完成请求数,衡量有效处理能力。

对照 KV 容量与队列状态定位瓶颈

结合缓存使用、等待请求和阶段耗时,判断延迟更可能来自容量不足、排队还是执行成本。

统一工作负载与基准测试口径

说明比较结果时需要统一模型、硬件、输入输出长度分布、到达率和缓存条件等实验设置。

附录:计算与存储成本

A. 参数量与模型权重占用

按模块汇总可学习参数,并结合存储精度估算模型权重占用。

B. KV Cache 容量计算

根据层数、KV Heads、Head 维度、缓存长度和元素字节数,估算给定架构下的 KV 容量。

C. Prefill 与 Decode 的 FLOPs

从矩阵形状推导两阶段的主要运算量,并说明计算口径与简化假设。

D. FlashAttention、显存带宽与实际执行时间

说明分块计算和减少中间结果读写如何影响实际执行效率,以及 FLOPs 为何不能直接代表延迟。

E. 参考资料

汇总正文使用的论文、官方文档与实现资料,注明各自支持的机制和适用范围。

Backlinks

Connections will appear here as the garden grows.

Related Notes

Explore the notes garden →