add decode throughput analysis
This commit is contained in:
299
worklogs/decode_analysis_report_2026-07-14.md
Normal file
299
worklogs/decode_analysis_report_2026-07-14.md
Normal file
@@ -0,0 +1,299 @@
|
||||
# Decode 吞吐专项实验分析报告
|
||||
|
||||
日期:2026-07-14
|
||||
|
||||
## 一、结论摘要
|
||||
|
||||
本轮实验确认:当前服务的主要短板是 decode 阶段吞吐,而不是 prompt prefill、tool parser 或 reasoning parser。
|
||||
|
||||
核心证据:
|
||||
|
||||
- 短 prompt、单并发、256 token 输出时,Output TPS P10 只有 `8.3-8.7 tok/s`,明显低于官方目标 `>=20 tok/s`。
|
||||
- 去掉 `--enable-auto-tool-choice`、`--tool-call-parser`、`--reasoning-parser` 后,decode TPS 没有提升,反而略低。
|
||||
- 加并发后没有获得 batch 增益:并发 1 聚合约 `8.00 tok/s`,并发 2 聚合约 `7.23 tok/s`,并发 4 聚合约 `5.08 tok/s`。
|
||||
- 并发 2 时硬件采样显示平均 GPU-Util 只有 `28.9%`,平均功耗约 `49.7W / 250W`,说明 GPU 没有被持续打满。
|
||||
|
||||
初步判断:瓶颈更像是 decode 路径中的调度、TP 同步、MoE kernel/专家路由、paged attention/kernel launch 开销,或 xFormers 后端限制,而不是 API parser 层。
|
||||
|
||||
## 二、实验环境
|
||||
|
||||
远端服务:
|
||||
|
||||
- 模型:`/root/public-storage/models/Qwen/Qwen3.6-35B-A3B`
|
||||
- API:`vllm.entrypoints.openai.api_server`
|
||||
- GPU:4 x Iluvatar BI-V100, 32GB
|
||||
- 当前主要实验配置:
|
||||
- `-tp 4`
|
||||
- `--gpu-memory-utilization 0.95`
|
||||
- `--max-num-seqs 2`
|
||||
- `--max-num-batched-tokens 8192`
|
||||
- `--enable-chunked-prefill`
|
||||
- `--enable-prefix-caching`
|
||||
|
||||
本地脚本:
|
||||
|
||||
- `worklogs/decode_microbench.py`
|
||||
|
||||
远端脚本:
|
||||
|
||||
- `/root/work/decode_microbench.py`
|
||||
|
||||
本地原始结果:
|
||||
|
||||
- `worklogs/remote_results/2026-07-14-decode/`
|
||||
|
||||
## 三、实验结果
|
||||
|
||||
### 1. 纯短 prompt decode 基线
|
||||
|
||||
完整 parser 配置,短 prompt,单并发,3 请求,每请求 `max_tokens=256`。
|
||||
|
||||
结果文件:
|
||||
|
||||
- 远端:`/root/work/logs/decode_full_parser_short_c1_t256_r3.json`
|
||||
- 本地:`worklogs/remote_results/2026-07-14-decode/decode_full_parser_short_c1_t256_r3.json`
|
||||
|
||||
指标:
|
||||
|
||||
| 指标 | 数值 |
|
||||
|---|---:|
|
||||
| 成功率 | 100% |
|
||||
| TTFT P90 | 1.85s |
|
||||
| Output TPS P10 | 8.74 tok/s |
|
||||
| Output TPS P50 | 8.74 tok/s |
|
||||
| 聚合 Output TPS | 8.34 tok/s |
|
||||
| 总 completion tokens | 768 |
|
||||
| reasoning tokens | 768 |
|
||||
|
||||
解释:
|
||||
|
||||
短 prompt 下 TTFT 已经较低,但 decode 速度仍只有约 `8.7 tok/s`。这说明长上下文不是唯一问题,短输出生成本身就偏慢。
|
||||
|
||||
### 2. Tool/parser 触发场景
|
||||
|
||||
完整 parser 配置,携带 29 个 tools,单并发,3 请求,每请求 `max_tokens=128`。
|
||||
|
||||
结果文件:
|
||||
|
||||
- 远端:`/root/work/logs/decode_full_parser_tool_c1_t128_r3.json`
|
||||
- 本地:`worklogs/remote_results/2026-07-14-decode/decode_full_parser_tool_c1_t128_r3.json`
|
||||
|
||||
指标:
|
||||
|
||||
| 指标 | 数值 |
|
||||
|---|---:|
|
||||
| 成功率 | 100% |
|
||||
| TTFT P90 | 4.98s |
|
||||
| Output TPS P10 | 8.70 tok/s |
|
||||
| Output TPS P50 | 8.70 tok/s |
|
||||
| 聚合 Output TPS | 7.38 tok/s |
|
||||
| prompt tokens | 6639 |
|
||||
| cached tokens | 4416 |
|
||||
| completion tokens | 384 |
|
||||
|
||||
单请求细节:
|
||||
|
||||
- 第 1 个请求:TTFT `5.97s`,cached tokens `0`
|
||||
- 第 2/3 个请求:TTFT 约 `1.0s`,cached tokens `2208`
|
||||
|
||||
解释:
|
||||
|
||||
工具 schema 会明显影响首次 prefill/TTFT,但前缀缓存命中后 TTFT 恢复。Output TPS 仍约 `8.7 tok/s`,与纯短 prompt 基本一致,所以 tool parser 不是 decode TPS 主瓶颈。
|
||||
|
||||
### 3. Parser-off 对照
|
||||
|
||||
重启服务,去掉:
|
||||
|
||||
- `--enable-auto-tool-choice`
|
||||
- `--tool-call-parser qwen3_coder`
|
||||
- `--reasoning-parser qwen3`
|
||||
|
||||
其余参数保持一致。
|
||||
|
||||
短 prompt,单并发,3 请求,每请求 `max_tokens=256`。
|
||||
|
||||
结果文件:
|
||||
|
||||
- 远端:`/root/work/logs/decode_noparser_short_c1_t256_r3.json`
|
||||
- 本地:`worklogs/remote_results/2026-07-14-decode/decode_noparser_short_c1_t256_r3.json`
|
||||
|
||||
指标:
|
||||
|
||||
| 指标 | 完整 parser | parser-off |
|
||||
|---|---:|---:|
|
||||
| 成功率 | 100% | 100% |
|
||||
| TTFT P90 | 1.85s | 3.18s |
|
||||
| Output TPS P10 | 8.74 | 8.30 |
|
||||
| Output TPS P50 | 8.74 | 8.33 |
|
||||
| 聚合 Output TPS | 8.34 | 7.87 |
|
||||
|
||||
解释:
|
||||
|
||||
关闭 parser 没有改善 decode。parser/reasoning/tool 相关启动项不是当前 decode 吞吐低的主因。
|
||||
|
||||
### 4. 并发曲线
|
||||
|
||||
parser-off 服务,短 prompt,每请求 `max_tokens=128`。
|
||||
|
||||
结果文件:
|
||||
|
||||
- `decode_noparser_short_c1_t128_r4.json`
|
||||
- `decode_noparser_short_c2_t128_r4.json`
|
||||
- `decode_noparser_short_c4_t128_r4.json`
|
||||
|
||||
指标:
|
||||
|
||||
| 并发 | 请求数 | 成功率 | TTFT P90 | Output TPS P10/请求 | 聚合 Output TPS |
|
||||
|---:|---:|---:|---:|---:|---:|
|
||||
| 1 | 4 | 100% | 0.79s | 8.30 | 8.00 |
|
||||
| 2 | 4 | 100% | 0.92s | 3.68 | 7.23 |
|
||||
| 4 | 4 | 100% | 51.60s | 2.57 | 5.08 |
|
||||
|
||||
解释:
|
||||
|
||||
并发提高后没有形成有效 batch 增益。并发 2 时单请求 TPS 近似减半,聚合 TPS 也略降;并发 4 时出现明显排队,TTFT P90 被拉到 `51.6s`。
|
||||
|
||||
这说明当前配置下 decode 并发能力很弱。由于服务参数 `--max-num-seqs=2`,并发 4 的后两个请求排队符合预期;但并发 2 聚合吞吐仍不提升,说明 decode 内部没有把双请求 batch 变成更高硬件利用率。
|
||||
|
||||
### 5. 硬件利用率采样
|
||||
|
||||
parser-off 服务,并发 2,4 请求,每请求 `max_tokens=128`,同时采样 `ixsmi`。
|
||||
|
||||
结果文件:
|
||||
|
||||
- 远端:`/root/work/logs/decode_noparser_short_c2_t128_r4_monitor.json`
|
||||
- 远端:`/root/work/logs/ixsmi_noparser_short_c2_t128_r4_monitor.json`
|
||||
- 本地同名文件位于:`worklogs/remote_results/2026-07-14-decode/`
|
||||
|
||||
指标:
|
||||
|
||||
| 指标 | 数值 |
|
||||
|---|---:|
|
||||
| 成功率 | 100% |
|
||||
| TTFT P90 | 0.92s |
|
||||
| Output TPS P10 | 3.79 tok/s |
|
||||
| 聚合 Output TPS | 7.40 tok/s |
|
||||
| ixsmi records | 52 |
|
||||
| parsed GPU samples | 208 |
|
||||
| 平均 GPU-Util | 28.91% |
|
||||
| 最大 GPU-Util | 100% |
|
||||
| 平均显存 | 30477 MiB |
|
||||
| 最大显存 | 30555 MiB |
|
||||
| 平均功耗 | 49.67 W |
|
||||
| 最大功耗 | 51 W |
|
||||
|
||||
解释:
|
||||
|
||||
GPU 利用率和功耗都偏低。虽然瞬时 GPU-Util 能到 100%,但平均只有约 29%,功耗长期接近空载到轻载水平。这说明 decode 过程中存在大量空泡、同步等待或小 kernel 启动开销,GPU 算力没有被持续喂满。
|
||||
|
||||
## 四、瓶颈判断
|
||||
|
||||
当前最可能的瓶颈排序:
|
||||
|
||||
1. Decode 调度/后端限制
|
||||
- `--num-scheduler-steps 4` 曾尝试失败。
|
||||
- 报错:`Multi-Step + Chunked-Prefill not supported for attention backend: xformers`。
|
||||
- 当前服务日志显示使用 `XFormers backend`。
|
||||
|
||||
2. TP 通信或同步开销
|
||||
- 模型使用 `-tp 4`。
|
||||
- 短 decode 每步都可能涉及多卡同步。
|
||||
- 并发 2 聚合 TPS 不升反降,符合小 batch 多卡同步效率差的特征。
|
||||
|
||||
3. MoE decode kernel/专家路由效率
|
||||
- Qwen3.6-35B-A3B 是 MoE 模型。
|
||||
- decode batch 小时,专家路由和 fused MoE kernel 可能难以形成高利用率。
|
||||
|
||||
4. Paged attention / attention backend 每 token 开销
|
||||
- 当前 attention 后端为 xFormers。
|
||||
- multi-step decode 被 xFormers + chunked prefill 组合限制。
|
||||
|
||||
5. API/parser 层
|
||||
- 本轮实验基本排除其为主瓶颈。
|
||||
- tool/schema 影响首次 TTFT,但不显著影响 decode TPS。
|
||||
|
||||
## 五、下一步建议
|
||||
|
||||
建议下一步不要直接改大段 kernel,而是先做两个能明确指向代码修改方向的服务变体实验。
|
||||
|
||||
### 实验 A:decode-only multi-step 变体
|
||||
|
||||
目的:验证 multi-step scheduling 是否能明显提升 decode。
|
||||
|
||||
做法:
|
||||
|
||||
- 暂时关闭 `--enable-chunked-prefill`
|
||||
- 加回 `--num-scheduler-steps 4`
|
||||
- 保持 `max_num_seqs=2`
|
||||
- 跑短 prompt decode 并发 1/2 曲线
|
||||
|
||||
判断:
|
||||
|
||||
- 如果 Output TPS 明显提升,说明 decode 调度是关键方向。
|
||||
- 后续要研究如何让 multi-step 与长上下文 chunked prefill 共存,或按场景切换。
|
||||
|
||||
风险:
|
||||
|
||||
- 官方长上下文负载仍需要 chunked prefill,所以这不是最终配置,只是定位实验。
|
||||
|
||||
### 实验 B:attention backend 变体
|
||||
|
||||
目的:确认是否可以启用兼容 multi-step 的 attention backend。
|
||||
|
||||
做法:
|
||||
|
||||
- 尝试设置 `VLLM_ATTENTION_BACKEND=FLASH_ATTN`
|
||||
- 或检查 CoreX/xFormers flash attention 能否被 vLLM selector 选中
|
||||
- 如果能启动,再测试 multi-step + chunked prefill
|
||||
|
||||
判断:
|
||||
|
||||
- 如果 flash attention 能启动且 multi-step 可用,优先走 backend 配置/适配路线。
|
||||
- 如果不能启动,需要看 `vllm/attention/selector.py`、`vllm/attention/backends/*` 和 CoreX xFormers 补丁。
|
||||
|
||||
### 实验 C:代码级 profiling
|
||||
|
||||
目的:把低 GPU 利用率归因到具体模块。
|
||||
|
||||
建议插桩位置:
|
||||
|
||||
- `vllm/worker/model_runner.py`
|
||||
- `vllm/worker/multi_step_model_runner.py`
|
||||
- `vllm/model_executor/models/qwen3_moe.py`
|
||||
- `vllm/model_executor/layers/fused_moe/*`
|
||||
- `attention.py`
|
||||
- `paged_attn.py`
|
||||
|
||||
记录每步:
|
||||
|
||||
- model forward 耗时
|
||||
- attention 耗时
|
||||
- MoE/MLP 耗时
|
||||
- sampler 耗时
|
||||
- 每步前后同步耗时
|
||||
|
||||
### 实验 D:服务参数小网格
|
||||
|
||||
目的:确认当前 `max_num_seqs=2` 是否已经是最优。
|
||||
|
||||
建议组合:
|
||||
|
||||
| 参数 | 候选 |
|
||||
|---|---|
|
||||
| `max_num_seqs` | 1, 2, 4 |
|
||||
| `max_num_batched_tokens` | 4096, 8192 |
|
||||
| `chunked_prefill` | on/off |
|
||||
| `num_scheduler_steps` | 1, 4 |
|
||||
|
||||
优先只在短 prompt decode 上跑,快速筛掉无效组合。
|
||||
|
||||
## 六、当前推荐行动
|
||||
|
||||
下一步优先跑:
|
||||
|
||||
1. `chunked_prefill=off + num_scheduler_steps=4`
|
||||
2. 若能启动,跑 decode c1/c2/c4 曲线和 ixsmi 采样
|
||||
3. 若 decode TPS 明显提升,再研究如何兼容官方长上下文 prefill
|
||||
4. 若没有提升,进入 qwen3_moe / fused_moe / attention 的代码级 profiling
|
||||
|
||||
本轮最重要的事实是:GPU 平均利用率只有约 `29%`,所以先不要把问题简单归因为“卡算不动”。更像是当前 decode 执行路径没有把四张卡持续喂满。
|
||||
Reference in New Issue
Block a user