Chunked Prefill 深入分析:调度、Chunk Size 与 Attention 形状
从调度合同、Attention/GEMM 形状与验收矩阵理解 Chunked Prefill 的收益和边界
Chunked Prefill 把一个长 Prompt 的 Prefill 拆成多个可调度片段。它改变的是一次连续占用 GPU 的时间与每轮 kernel shape,不会凭空减少 Prompt token、最终 KV Cache 或完整模型计算。
这篇聚焦“怎么切、切完改变了什么、如何验收”。Continuous Batching 与 KV 分页的基础合同见 批处理与调度 和 KV Cache。
- 一句话:Chunked Prefill 用多轮 scheduler token budget 换取更细的抢占点,并在 TTFT、TPOT、吞吐和资源峰值之间做权衡。
- 三个判断:Decode backlog 高时小 chunk 更可能保护 TPOT;Prefill kernel 过碎时大 chunk 更可能保护 TTFT/吞吐;P/D 分离后它仍可控制 Prefill 池公平性、峰值和 KV 发送节奏。
- 核心模型:,且 Attention 形状为 。
- 边界:最佳 chunk 不能从原始 ISL 或框架默认值推出,必须结合 effective prefill、并发、MoE 路由、硬件和 SLO 实测。
1. 问题与调度合同
如果调度器把长 Prompt 当作不可切分任务,它可能在一次较长的 Prefill 中延迟已有 Decode:
完整 Prefill:
decode -> [ long prefill ---------------- ] -> decode
Chunked Prefill:
decode -> [chunk] -> decode -> [chunk] -> decode
同一个请求必须完成自己的全部 Prefill 后才能开始 Decode。交错发生在不同请求之间:A 的长 Prompt 尚未完成时,B/C 的 Decode 可以在 chunk 边界继续推进。
设请求还剩 个输入 token,本轮可分配 budget 为 :
是 scheduler chunk,不是模型层内部的 tile,也不是固定配置里的最大上下文。总 budget 还要容纳其他 Prefill 和 Decode token:
Chunked Prefill 的直接收益是新增调度边界;直接代价是更多轮 scheduler、元数据准备和 kernel 启动。
2. Chunk Size 改变哪些底层形状
设第 个 chunk 新处理 个 token,之前已有 个 token 的 KV。
Attention
新 token 既要看本 chunk 中较早的 token,也要看过去的 KV:
其 causal attention 工作量可近似写成:
因此:
- 后续 chunk 即使 相同,也会因 增长而更重;
- 切块前后的理论总 Attention 工作量接近,主要变化是 shape 与执行粒度;
- prefix hit 后,suffix 的 变短,但 仍包含 cached prefix,计算不一定按 miss token 比例线性下降。
Dense FFN / GEMM
本轮多个请求可在 token 维 flatten:
X: [total_scheduled_tokens, hidden]
W: [hidden, intermediate]
chunk 太小会缩短 GEMM 的 维,让 launch、调度和小 shape 效率更显著;多个小请求合批则可能重新撑大 。
MoE
MoE 还要经过 routing。每个 expert 实际收到的 token 数取决于本轮总 token、top-k 与路由分布:
小 chunk 可能让 grouped GEMM 变碎,并增加 dispatch/combine 相对占比。Dense 模型上的最佳值不能直接复用到 MoE。
3. 四个核心权衡
| 目标 | 一般倾向 | 需要同时观察 |
|---|---|---|
| 保护 Decode TPOT/ITL 尾部 | 更小 chunk | Decode backlog、scheduling gap |
| 缩短长请求 TTFT | 更大 chunk | 排队、完整 Prefill 轮数 |
| 提高 tokens/s/GPU | 中到大 chunk | Attention/GEMM/MoE shape |
| 控制 activation/workspace 峰值 | 小到中 chunk | KV 水位、并发、抢占 |
这不是单调关系。chunk 变小后,TPOT 可能改善,也可能因 engine overhead 与碎片化反而恶化;chunk 变大后,单次 kernel 更高效,也可能制造更长的不可抢占区间。
真正的优化目标应写成带约束的问题,例如:
4. Policy:固定值之外还要看什么
4.1 Effective Prefill
原始输入长度不是本轮实际计算量:
若复用 KV 在 CPU、SSD 或远端,还要单独加入加载/传输延迟,不能把 cache hit 当作免费。
4.2 Decode Backlog
一个简单的自适应策略是:
decode backlog 高 -> 降低 chunk 上限,增加让出机会
decode backlog 低 -> 提高 chunk 上限,尽快完成 Prefill
它只是起点。若 workload 抖动大,还需 hysteresis、最小 chunk 与最大等待时间,避免策略来回震荡。
4.3 Length Bucket
Bucket 决定请求进入哪个队列或 worker,chunk 决定单请求本轮推进多少 token:
| 输入形态 | 可评估策略 |
|---|---|
| 短 Prompt | 不切或较大 chunk,优先 TTFT |
| 中等 Prompt | 结合 backlog 调整 |
| 长 Prompt | 限制单轮占用,保护公平性 |
| 超长 Prompt | chunk + admission control + KV 水位保护 |
4.4 Tail Chunk
最后一个很小的 chunk 可能产生低效 shape。可以评估合并尾块、设置最小粒度或允许最后一轮超出软 budget,但必须确认不会破坏 Decode SLO 与显存上限。
5. 在聚合式与 P/D Serving 中的含义
| 部署形态 | Chunked Prefill 的主要作用 | 新增关注点 |
|---|---|---|
| Prefill/Decode 同池 | 在长 Prefill 间插入 Decode,降低阶段干扰 | TTFT 与 TPOT 权衡 |
| P/D 分离 | Prefill 池内公平、峰值控制、KV 生成/发送粒度 | KV transfer、Prefill queue |
P/D 分离不会自动消除长短 Prompt 竞争;它只是把 Decode 移出这组竞争。若 KV 只能在完整 Prefill 后发送,chunk 也不会自动形成传输流水,需要以 connector 的真实生命周期为准。
框架是否支持分块发送、流控和失败恢复,属于 Serving Stack 与框架选型 的实现合同。
6. 最小实验与验收
第一轮实验应固定模型、精度、硬件、engine 版本和 workload,仅扫描 chunk/token budget:
| 维度 | 建议覆盖 |
|---|---|
| 输入 | 短、中、长、超长桶;同时记录 effective prefill |
| 输出 | 短输出与长输出,改变 Decode backlog |
| 并发 | 低、中、高或明确 arrival process |
| 模型 | dense / MoE / hybrid attention |
| cache | miss、典型 hit、远端 KV load |
至少采集:
request_id, phase, chunk_id, token_range,
scheduled_tokens, past_kv_tokens, prefix_hit_tokens,
batch_num_seqs, batch_num_tokens,
TTFT, TPOT/ITL, throughput, SLO-goodput,
scheduling_gap, KV_watermark, preemption_count,
kernel_name, kernel_shape, kernel_duration
推荐先画四条曲线:
chunk size -> TTFT P99
chunk size -> TPOT/ITL P99
chunk size -> SLO-goodput
chunk size -> kernel duration + scheduling gap
读图时遵循:
- chunk 变小而 TPOT 不改善:阶段干扰可能不是主因;
- TTFT 明显恶化、TPOT 改善很小:chunk 可能过碎;
- 吞吐下降且 kernel 时间分散:检查 shape、plan 与 launch overhead;
- MoE grouped GEMM / all-to-all 占比上升:检查每个 expert 的 token group。
7. 查证层:框架如何表达 Chunk
vLLM / TensorRT-LLM 参数如何映射到合同
不同版本的参数名与默认值会变化,使用时应查目标版本文档和启动配置。
在 vLLM 中,常见控制面包括:
| 参数族 | 合同含义 |
|---|---|
max_num_batched_tokens | 单轮 token budget |
max_num_seqs | 单轮 sequence 上限 |
| partial-prefill / long-prefill 参数 | 同时允许多少 partial prefill,以及长请求策略 |
Scheduler 输出每个 request 的 num_scheduled_tokens。Model runner 可把本轮 token flatten 成:
total_num_scheduled_tokens = sum(request.num_scheduled_tokens)
hidden = [total_num_scheduled_tokens, hidden_size]同时保留 query_start_loc、seq_lens、block_table,确保不同请求的 Attention 不互相可见。
TensorRT-LLM 常把相关能力描述为 chunked context / chunked prefill,并与单轮 token 上限、paged KV 和 in-flight batching 联动。概念对应,不应假定参数名、默认策略或边界完全一致。
Trace 里哪些信号不能直接当成 Chunk Size
Attention backend 的 plan/run 次数可能对应模型结构,而不是 scheduler chunk 数。已有 Qwen3.5 Plus GB300 trace 中,前 64 个采集 step 出现 15 plan/run,与 60 层模型中每四层一个 full-attention layer 的结构相符;它不能证明 chunk 是 15 token 或 15 个请求。
同一 trace 最后一个采集窗口只有 2 plan/run 与 11 个 state/KV save 信号,但采集几乎贴着 execute_model 结束。它只能证明窗口中的最后一步不完整,不能单独断言是请求的最终 tail chunk。
要确认 chunk,优先找 scheduler 侧的 num_scheduled_tokens、token_range、num_computed_tokens 和 request/chunk identity。混合 GDN 模型内部的 64-token kernel chunk 见 GDN 与 Chunked Prefill,完整案例诊断见 Prefill Trace。
8. 常见误区
- 把它当成减少 Prefill FLOPs:它首先改变调度粒度;prefix reuse、模型压缩或更快 kernel 才可能减少/加速实际工作。
- 只按 raw ISL 分桶:应同时看 prefix hit、KV load 与 effective prefill。
- 把一个默认值套到所有硬件:算力、HBM、互联和 kernel 实现都会改变拐点。
- 只看平均吞吐:流式服务必须同时看 TTFT、TPOT 尾部和 SLO-goodput。
- 混淆 scheduler chunk 与 kernel chunk:前者分配请求 token,后者是算子内部实现。
- 从 trace 次数反推 token 数:没有 request identity 与 token range 时只能提出假设。
9. 模拟器接口
模拟器不应只使用一个总 Prefill 时间。更可解释的形式是:
Decode 受到的阻塞取决于实际交错顺序,而不只是 Prefill 总 FLOPs。参数来自 trace 或校准表时,应保存硬件、engine 版本、模型、精度和 workload identity;缺失值不得默认为零。
相关页面
- 批处理与调度
- GDN 与 Chunked Prefill
- Prefill Trace
- Causal Attention 与 KV hit 面积模型
- KV Cache Hit Ratio 修正模型
- Serving Stack 与框架选型
参考资料
← 被以下页面引用(6)
- 模拟器建模指南:显存与吞吐公式ai-systems · synthesis
- 推理框架对比 2026:从 Engine 到 Serving Stackai-systems · synthesis
- LLM 推理系统全栈地图ai-systems · synthesis
- Prefill Trace:Worker 供给、DSA/MLA 与 Chunked Prefillai-systems · synthesis
- 批处理与调度:推理服务的灵魂ai-systems · concept
- GDN 与 Chunked Prefill:为什么 prepare_chunk_indices 会出现在 trace 里ai-systems · concept
修改历史5 次提交
- docs: refine LLM inference knowledge systemxiaocheng··
f8756b9 - docs(wiki): render inference formulas with latexxiaocheng··
6c51439 - feat(wiki): connect core topics and add reading seriesxiaocheng··
9fc9884 - feat(wiki): strengthen discovery and content lifecyclexiaocheng··
6e0862f - docs(wiki): publish July inference researchxiaocheng··
0a9b76b