sskj/docs/Kimi-K3_PD-DFlash_16K512_C8性能归因.md
2026-09-02 11:16:53 +08:00

10 KiB
Raw Blame History

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/BNsight/PyTorch Trace 只用于归因。

3. 严格 A/B 配置

项目 P 组 D 组
节点 601-604 605-608
并行 TP4 / PP8 / EP4 TP32 / PP1 / EP4
MoE FlashInfer MXFP4A2A none FlashInfer MXFP4A2A none
Chunk 8192 8192
KV Cache BF16 BF16
请求上限 / CUDA Graph BS 8 / 8 8 / 8
显存比例 0.84 0.86
传输 Mooncakemlx5_0/1/2/3 Mooncakemlx5_0/1/2/3

请求固定为同一批 SPEED-Bench 数据40 请求C=8输出 512实际输入共 666,343 tokenwarmup=1seed=42temperature=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 stagePP7/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_0 RX P95 约 39.25-39.38 Gbit/s
  • mlx5_2 TX 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 ErrorD 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. 后续优化顺序

  1. 先减少 PD 交接内容:确认哪些 draft/KDA buffer 必须由 P 传输,哪些可以由 D 本地重建或延迟生成;用 payload/request 和 TTFT waterfall 验收。
  2. 降低 D 侧通信固定成本:针对 TP32 小消息 AllReduce 比较更小通信域或 per-op Tree必须保持同一 SPEED-Bench 复测正确性、TPOT 与接受长度。
  3. 搜索 DFlash 的收益边界:固定 PD 拓扑,扫 draft token 数和 tree 参数,目标是提高接受长度同时减少 verify 次数;不要只看接受长度,要看 accepted tokens / speculative cycle cost
  4. 最后再调 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/