10 KiB
Kimi-K3 PD+DFlash 16K→512、C=8 性能归因
更新时间:2026-09-02
1. 目标与结论
本实验在 8 台 RTX 6000D 上,用同一镜像、同一 SPEED-Bench 请求和同一服务参数,对比:
- 标准 PD,无投机解码;
- PD+DFlash;
- 历史 PP8 双实例无投机结果,用作同数据集拓扑参考。
核心结论:当前 PD+DFlash 同时放大了 P→D 交接成本和 D 侧单步成本,平均接受长度 3.69 不足以覆盖这些开销。瓶颈不是 400G Rail 被打满。
与严格同口径 PD 无投机相比,PD+DFlash:
- P→D 每请求交接数据约从
85.76 MB增至183.54 MB,增加114.0%; - D 侧 transfer wait 窗口从
15.24 s增至22.24 s,增加7.00 s; - Mean TTFT 增加
7.40 s,其中 transfer wait 增量相当于 TTFT 增量的94.5%; - Mean TPOT 增加
41.9%,Input/Output TPS 均下降29.0%; - Nsight 中
_fwd_kernel占 GPU kernel 时间49.8%,NCCL AllReduce 占31.9%,两者远高于 MoE/GEMM。
这里的 transfer wait 是 D 请求进入后等待 P 完成计算、bootstrap/注册并交付数据的整段窗口,不等于纯 RDMA wire time。
2. 指标口径
设第 i 个请求的发出、首 token、结束时刻为 s_i/f_i/e_i,输入和输出 token 数为 I_i/O_i,整轮 benchmark 墙钟时间为 D:
| 指标 | 计算方式 | PD 场景中的含义 |
|---|---|---|
| TTFT | f_i - s_i |
Router、P 排队/Prefill、P→D 交接、D 接入及首 token 的总和 |
| TPOT | (e_i - f_i) / (O_i - 1) |
首 token 后平均每个输出 token 的耗时,主要由 D 侧决定 |
| E2E | e_i - s_i |
完整请求延迟 |
| Input TPS | ΣI_i / D |
整个系统墙钟吞吐,不是 P 的纯 Prefill 算力 |
| Output TPS | ΣO_i / D |
整个系统墙钟吞吐,不等于 1 / Mean TPOT |
DP、Router 和 PD 不改变公式,只改变时间花在哪个阶段。Profiler 本身开销很大,因此性能数字只取无 profiler 的严格 A/B;Nsight/PyTorch Trace 只用于归因。
3. 严格 A/B 配置
| 项目 | P 组 | D 组 |
|---|---|---|
| 节点 | 601-604 | 605-608 |
| 并行 | TP4 / PP8 / EP4 | TP32 / PP1 / EP4 |
| MoE | FlashInfer MXFP4,A2A none | FlashInfer MXFP4,A2A none |
| Chunk | 8192 | 8192 |
| KV Cache | BF16 | BF16 |
| 请求上限 / CUDA Graph BS | 8 / 8 | 8 / 8 |
| 显存比例 | 0.84 | 0.86 |
| 传输 | Mooncake,mlx5_0/1/2/3 | Mooncake,mlx5_0/1/2/3 |
请求固定为同一批 SPEED-Bench 数据:40 请求,C=8,输出 512,实际输入共 666,343 token,warmup=1,seed=42,temperature=0。DFlash 的 draft token 数为 16。
镜像:
local/sglang:kimi-k3-pp-dflash-33863-fi0618-situ4460-kvbounds1
4. 端到端结果
| 指标 | PP8 双实例无投机(历史参考) | 严格 PD 无投机 | 严格 PD+DFlash | DFlash vs PD 无投机 |
|---|---|---|---|---|
| 成功请求 | 40 | 40 | 40 | - |
| Benchmark duration | 335.95 s | 255.29 s | 359.53 s | +40.8% |
| Input TPS | 1983.46 | 2610.18 | 1853.35 | -29.0% |
| Output TPS | 60.96 | 80.22 | 56.96 | -29.0% |
| Mean TTFT | 6.88 s | 15.40 s | 22.80 s | +48.1% |
| Median TTFT | 7.04 s | 16.03 s | 23.07 s | +43.9% |
| P95 TTFT | 10.64 s | 22.18 s | 40.54 s | +82.8% |
| Mean TPOT | 116.13 ms | 63.22 ms | 89.70 ms | +41.9% |
| P95 TPOT | 136.01 ms | 70.45 ms | 144.76 ms | +105.5% |
| Mean E2E | 66.22 s | 47.70 s | 68.63 s | +43.9% |
| DFlash 接受长度 | - | - | 3.69 | - |
PP8 双实例结果使用相同数据,但缺少本轮完整命令归档,只作为拓扑参考。严格单变量结论来自后两列。
5. TTFT 瀑布拆解
从 P 最后一个 PP stage(PP7/TP0)和 D TP0 日志中去重,排除 warmup 后取正式 40 请求:
| 阶段 | PD 无投机 | PD+DFlash | 变化 |
|---|---|---|---|
| P bootstrap | 5.18 s | 6.67 s | +28.7% |
| P forward | 9.51 s | 14.22 s | +49.5% |
| P queue | 1.94 s | 0.93 s | -52.3% |
| P→D payload / 请求 | 85.76 MB | 183.54 MB | +114.0% |
| D bootstrap | 5.15 ms | 4.85 ms | 基本不变 |
| D allocation wait | 12.67 ms | 2.78 ms | 可忽略 |
| D queue | 0.41 ms | 0.30 ms | 可忽略 |
| D transfer wait | 15.24 s | 22.24 s | +45.9% |
| D forward | 32.35 s | 46.10 s | +42.5% |
5.1 为什么说 PD 交接冲散了收益
DFlash 需要向 D 节点交接额外的 draft/KDA 状态,使每请求 payload 增加约 97.78 MB。D 侧 transfer wait 随之增加 6.998 s,而 Mean TTFT 总共增加 7.402 s。两者不是可相加的独立阶段,但增量高度一致,说明 TTFT 回退主要发生在 P 计算与 P→D 交接链路,而不是 D admission 排队。
5.2 为什么不能把 22.24 秒叫作 RDMA 拷贝耗时
该时间戳从 D 开始等待传输到请求可进入 forward,覆盖:
P 侧计算/准备 → Mooncake bootstrap 与 buffer 注册 → 数据传输 → D 侧完成可用
因此它是协议端到端等待窗口。纯线速传输 183.54 MB 即使只用一条 400G Rail,理论时间也只有毫秒级;当前几十秒来自依赖链、同步与大量小通信,而不是字节在线上连续搬运了几十秒。
6. RDMA 与 GPU 证据
严格 DFlash run 的 D 节点活跃 Rail:
mlx5_0RX P95 约39.25-39.38 Gbit/s;mlx5_2TX P95 约39.14-39.23 Gbit/s;- 峰值约
42 Gbit/s; - 单 Rail 标称为 400G,当前峰值约为其 10%。
所以当前不是 raw bandwidth saturation。需要优化的是交接字节量、通信调用方式、同步依赖和通信域,而不是先增加 Rail 带宽。
严格 A/B 中 D 节点 GPU Util P95 均为 100%,DFlash D 节点平均利用率约 74%,并非 GPU 长期空闲等待网络;但高利用率不能区分有效计算、通信 kernel 和等待慢 rank,需结合 Nsight。
7. Nsight Systems 归因
Nsight 只包裹 D0 节点的 8 个本地 scheduler,保持 CUDA Graph 开启。Profile run 为 8 请求,仅用于时间线归因;其吞吐和延迟不能与无 profiler 结果比较。
7.1 全局 GPU kernel
| Kernel 类别 | GPU 时间 | 占比 | 调用数 |
|---|---|---|---|
_fwd_kernel |
14.59 s | 49.8% | 4,590 |
| NCCL AllReduce Ring LL BF16 | 9.34 s | 31.9% | 30,600 |
| MoE/GEMM 主 kernel | 约 1.0 s | 约 3.4% | - |
| NCCL AllGather | 0.53 s | 1.8% | - |
| KDA update | 0.42 s | 1.4% | - |
_fwd_kernel 通过 NVTX 相关性确定处于 DFlash target verify/draft forward 路径,但仅凭导出的 kernel 名还不能把它进一步等同为某个单一源码函数。
7.2 DFlash NVTX 阶段与 kernel
本轮额外标记:draft prepare、target verify、accept、ReplaySSM commit 和 draft KV materialize。
| NVTX 阶段 | 主要 GPU 内容 |
|---|---|
| Target verify | _fwd_kernel 51.0%;AllReduce 30.6%;MoE/GEMM 13.0%;AllGather 1.8% |
| Draft prepare/forward/sample | AllReduce 66.8%;_fwd_kernel 25.4%;MoE/GEMM 4.0%;AllGather 2.3% |
| Materialize draft KV | 主要为 GEMM/数据变换,GPU 总量较小 |
| ReplaySSM commit / accept | GPU 总量很小,不是主瓶颈 |
NVTX host range 平均每个 speculative cycle:
- target verify:约 18.07 ms;
- draft prepare/forward/sample:约 9.26 ms;
- materialize draft KV:约 1.44 ms;
- ReplaySSM commit:约 0.52 ms;
- accept:约 0.43 ms。
CUDA API 侧 cudaEventSynchronize 共约 24.34 s,占 CUDA API 时间 82.9%;cudaGraphLaunch 320 次、约 2.89 s。这说明 CUDA Graph 已生效,但每轮 speculative cycle 仍暴露出 target/draft/NCCL 依赖的同步等待。Graph 能减少 launch overhead,不能消除 collective 和状态依赖。
7.3 PyTorch Profiler 补充结果
PyTorch Profiler 已导出 P0 本地 PP0/PP1 的 8 份 trace,共约 117 MiB。但 P/D 的 /stop_profile 均返回 Internal Server Error,D trace 未落盘;profile 期间客户端流式 TTFT 也失真。因此本报告不从这轮生成新的性能结论,保留 P trace 供后续定位 Prefill operator stack。
实验入口已修正:P/D 的 stop_profile 改为并行请求并各自限时 180 秒,避免一侧导出异常让整轮实验永久挂起。
8. 两个问题的回答
8.1 PD 的收益为什么被传输冲散
不是单纯“网卡慢”,而是 DFlash 改变了 PD 协议要交接的内容:payload 翻倍、P 侧准备时间增加、D 侧必须等更多状态就绪。当前 D 侧 Rail 远未饱和,因此提升网卡带宽不会按比例降低 7 秒差额。
8.2 投机解码为什么收益很少,甚至变慢
平均接受长度 3.69 意味着一次 draft/verify 只推进约 3.69 个 token。每轮仍需:
draft forward/sample
→ target verify
→ 大量 TP32 AllReduce
→ KDA/ReplaySSM 状态处理
→ accept 与 KV materialize
Nsight 显示 target verify 和 AllReduce 已占关键路径。接受长度不足以摊薄这些成本,最终 D forward 增加 42.5%,TPOT 增加 41.9%。
9. 后续优化顺序
- 先减少 PD 交接内容:确认哪些 draft/KDA buffer 必须由 P 传输,哪些可以由 D 本地重建或延迟生成;用 payload/request 和 TTFT waterfall 验收。
- 降低 D 侧通信固定成本:针对 TP32 小消息 AllReduce 比较更小通信域或 per-op Tree;必须保持同一 SPEED-Bench 复测正确性、TPOT 与接受长度。
- 搜索 DFlash 的收益边界:固定 PD 拓扑,扫 draft token 数和 tree 参数,目标是提高接受长度同时减少 verify 次数;不要只看接受长度,要看
accepted tokens / speculative cycle cost。 - 最后再调 Mooncake/RDMA:只有 HCA 接近线速或纯传输微基准异常时,才把 Rail 带宽作为主优化项。
10. 原始证据
严格 PD 无投机:
/data/hzy/sskj/experiments/pro6000/kimi3_pro6000_pd_dflash_attribution/results/kimi3-pd-nospec-ab-pmem084-20260901-1808/
严格 PD+DFlash:
/data/hzy/sskj/experiments/pro6000/kimi3_pro6000_pd_dflash_attribution/results/kimi3-pd-dflash-ab-pmem084-20260901-1823/
Nsight:
/data/hzy/sskj/experiments/pro6000/kimi3_pro6000_pd_dflash_attribution/results/kimi3-pd-dflash-nsys-donly-20260902-100251/
/data/hzy/sskj/experiments/pro6000/kimi3_pro6000_pd_dflash_attribution/results/kimi3-pd-dflash-nsys-donly-20260902-100251/profiles/node_5/nsys/d0.nsys-rep
PyTorch Profiler(仅 P0 的 PP0/PP1 trace 有效):
/data/hzy/kimi3_pd_dflash_attribution/kimi3-pd-dflash-torch-retry-20260902-103042/torch/
PP8 双实例历史参考:
/data/cdflash_speedbench/matrix/bench_dual_16k_o512_c8.log
/data/cdflash_speedbench/matrix/bench_dual_16k_o512_c8.jsonl
本地归档:
/Users/hzy/Desktop/infra/docs/evidence/kimi_k3_pd_dflash_attribution/