# Kimi-K3 PP8 + DFlash PD:实现与验证 更新:2026-08-31。**八节点部署与固定 GSM8K 64 题 C1/C8 验证完成,128/128 请求成功,答案检查均通过,无输出截断。** 本次完成的是用户后续指定的 DFlash 路线,未恢复 EAGLE3/no-spec 实验。 ## 1. 目标与实现 保留 P 侧 PP8 的部署方案,让 P 生成真实 DFlash prompt KV,经 Mooncake 传给 D,D 接着执行投机解码。 ```text P 601-604:TP4 / PP8 / EP4 各 stage 采集 target hidden,计算局部投影 → PP stage 间累加投影结果 → 最后 stage 统一 RMSNorm,生成 6 层 draft KV → 传输 target MLA KV、KDA 状态及 draft KV D 605-608:TP32 / PP1 / EP4 接收上下文 → DFlash 提议 → target 验证 → 提交 token ``` 基于 SGLang PR #33863 固定提交 `6465a6f3d3b6c8b7fee40fba0fdc09cf5e9ca1c5`。分段投影复用该 PR 的设计;新增 DFlash worker、Kimi capture、PD 调度衔接和异构 TP 传输,保留已验证的 Kimi SM120 FlashInfer MXFP4 接入。 | 模块(相对于 `python/sglang/srt/`) | 本次改动 | |---|---| | `models/kimi_k3.py`、`speculative/dflash_pp.py` | 按 checkpoint 采集指定层;处理 PP 边界 residual;分段投影后只做一次归一化 | | `speculative/dflash_worker_v2.py` | 接收、传递 PP 上下文;最后 stage 写 draft KV;非末 stage 保留最小 KV pool | | `managers/scheduler_pp_mixin.py`、`speculative/spec_info.py` | 接通 DFlash proxy、PD 输入、FutureMap 与 idle 生命周期 | | `disaggregation/common/kv_entry_layout.py`、`mooncake/conn.py` 等 | target MLA 整页传输;draft GQA 按 head 交集逐 token 切片;独立计算源/目标 stride,在提交前检查边界 | | `model_executor/runner/base_runner.py`、`disaggregation/prefill.py` | 修复 P 普通预热误带 verify metadata,以及混合 KV 池传输层范围计算 | | `arg_groups/` | 仅放开已实现的 P 侧 PP + DFlash,D 侧保持 PP1 | 完整增量见 [pp_dflash_integration.patch](pp_dflash_integration.patch),19 个文件校验值见 [pp_dflash_files.json](pp_dflash_files.json)。独立源码位于 601 的 `/data/hzy/src/sglang-kimi-pp-dflash-33863`,不覆盖同事部署源码。 ## 2. 实际配置 | 项目 | 本次值 | |---|---| | GPU | 8 节点 × 8 张 RTX 6000D;每卡 85651 MiB,SM120,PCIe | | P / D 并行 | TP4/PP8/EP4;TP32/PP1/EP4 | | MoE / A2A | `flashinfer_mxfp4` / `none`,两组一致 | | Target / Draft KV | 均为 `bfloat16` | | Chunk / Page | 8192 / 64 | | 最大活跃请求 / Decode Graph BS | 8 / 8;D 日志确认实际 Decode 使用 CUDA Graph | | P / D 显存比例 | 0.88 / 0.86 | | P / D Mamba memory ratio | 0.36 / 0.21 | | Prefix Cache | `--disable-radix-cache`;128 个响应的 cached tokens 均为 0 | | RDMA | Mooncake,`mlx5_0,mlx5_1,mlx5_2,mlx5_3`,容器挂载 `/dev/infiniband` | | Draft | `/data/hf_models/Kimi-K3-DFlash`,6 层,hidden 7168,32 Q heads / 8 KV heads,head dim 128 | | Draft 上下文 | Sliding window 4096,RoPE theta 2000000,capture `[19,37,54,66,78,90]` | | Draft block | `--speculative-num-draft-tokens 16`;每个 verify step 统计 15 个 draft 候选位置 | 当前镜像:`local/sglang:kimi-k3-pp-dflash-33863-fi0618-situ4460-kvbounds1`。Linux/amd64 manifest 为 `e74c9b1e7fb6a9509db32576d2c9196b42ef329118909eeebd620cb9db2f91e9`;image config 为 `26584138eb1e097183ce167cbffe4198be0611e0cfde7422cbe692100d865982`。八节点镜像身份已核对。 FlashInfer 使用**官方 0.6.18 wheel + 已合并 #4460 的原样 backport**(`b460bc00cb373541102d2155aec35bd626e522ce`)。该 wheel 所属发布分支尚无 CUTLASS SiTU API,不能描述为“未经修改的 0.6.18 直接支持”。移除旧 cubin/JIT-cache 包,保留版本检查;编译缓存挂载到 `/data/hzy/cache/kimi-dflash-fi0618-situ4460`。最后两项启动修复仅替换 Python 层,不改变 FlashInfer kernel。 [Dockerfile](Dockerfile) 的完整重建输入保留在 601 本实验 `results/`:`sglang-kimi-pp-dflash-33863-integrated.tar.gz`(SHA256 `226065165bbb5f85ce516b847ff6da7e5aa823f12e69b87558e67c91996e3ba0`)和 `official_flashinfer_0618/flashinfer_python-0.6.18-py3-none-any.whl`(SHA256 `d5d26edb48f8def0bf28b2c94415aef7f0754e2cd9e3cb3d6e7081262d068aad`)。源码归档含固定上游 Python 树、补丁后的代码、3 个测试文件及 `SOURCE_MANIFEST.json`;GPU 测试和服务验证状态以外部结果日志为准,不回写构建时的历史 manifest。 ## 3. 测试结果 Run ID:`pd-dflash-kvbounds1-20260831-1740`。使用 GSM8K 实际文件前 64 题、5-shot、temperature=0、top_p=1,输入不裁剪,输出上限 512。实际输入 694-794 token,最长输出 225 token。C1 先运行,随后 C8;没有新增 no-spec 或 16K synthetic 测试。 | 指标 | C1 | C8 | |---|---:|---:| | 请求成功 / 计划 | 64/64 | 64/64 | | 答案检查通过 | 64/64 | 64/64 | | 排除与 5-shot 重叠的前 5 题后 | 59/59 | 59/59 | | 达到输出上限 | 0 | 0 | | 客户端总耗时 | 195.42 s | 55.55 s | | 总输出 token | 6523 | 6530 | | 整体 Output TPS | 33.38 | 117.56 | | 接口接受长度,每题等权平均 | 6.9433 | 7.0070 | | 直方图接受长度,按 verify 步数加权 | **6.4211** | **6.5158** | | Draft 接受率,不含 bonus | 36.14% | 36.77% | | Verify 步数 | 1026 | 1012 | | 接受 / 提议 draft token | 5562 / 15390 | 5582 / 15180 | | 请求回撤 | 0 | 0 | **这套 PP8 + PD + DFlash 已能完成本轮部署回归,接受长度没有停留在接近 1 的状态。** C8 的 117.56 token/s 是整体输出吞吐,包含 Prefill、传输、调度及 Decode,不是单请求 Decode 速度。本轮未重跑匹配的 no-spec 对照,不据此宣称投机加速倍数。 历史客户端的 5-shot 取自同一测试文件前 5 题,与这 64 题重叠,保留此口径用于历史部署回归。剩余 59 题也全部通过;本报告不将此结果作为独立无泄漏的模型能力评测。所有输出均包含 `####` 最终答案,已独立按带符号数值重新解析并与标签比对。 ### 接受长度为什么有两种数值 接口 `spec_accept_length` 在 `tokenizer_manager.py:2814` 定义为 `completion_tokens / spec_verify_ct`,受 P 侧首 token 和最后一步停止截断影响。例如一题输出 49 token、验证 3 次,接口值是 16.33;实际直方图为 3 次各接受 15 个 draft,含 bonus 的每步长度为 16,没有超出 block 能力。 ```text 加权接受长度 = 1 + 总接受 draft token / 总 verify 次数 C1 = 1 + 5562 / 1026 = 6.4211 C8 = 1 + 5582 / 1012 = 6.5158 ``` 128 题逐一验证了 `sum(histogram)=verify_ct`、直方图加权计数等于 `accepted_drafts`、`proposed_drafts=15×verify_ct`。接口原值完整保留。客户端是非流式,不由总耗时推造 TTFT/ITL。 ## 4. 验证与运行状态 - 24 项 CPU 回归通过:13 项 PP/PD、7 项传输、4 项 Kimi MoE,覆盖 PP1/2/4/8/16、BF16/FP32 分段投影、TP4→TP32 全部 GQA head 映射、越界拒绝及输入生命周期。 - 601 GPU6 的 Kimi SM120 SiTU 布局与非连续输入集成回归通过;固化镜像独立 GPU 复测 `1 passed`。CPU 回归使用实际方法的 AST 提取与 CPU tensor,不是完整模型 logits 等价测试。 - Router smoke 和正式 C1/C8 全部完成。D 日志有 RDMA ready ACK 与实际 Decode CUDA Graph 记录。 - 本 Run 服务日志未检出 Traceback、CUDA OOM、KVTransferError 或非法显存访问。存在 NUMA 查询权限警告和 K3 fused KDA decode 布局回退提示,未阻断本轮;后续性能调优可单独审查。 - 运行中显存快照:P 每卡 53361-76579 MiB,D 每卡 79849-80019 MiB。这是离散快照,不是全程峰值。 - 续跑和清理均退出 0。601-608 本实验容器已删除,GPU compute process 为空,显存回落到 0-3 MiB。 ## 5. 如何运行 唯一入口在 **601**;602-608 不需要手工再启动入口。配置见 [config.env](config.env),请求由 [bench_gsm8k_acceptance.py](bench_gsm8k_acceptance.py) 生成。维护既有 GitLab 分支 `hzy-kimi3-pd-pp8-standard`。 ```bash cd /data/hzy/sskj/experiments/pro6000/kimi3_pro6000_pd_dflash_validation # 展开命令,不使用 GPU DRY_RUN=1 RUN_ID=pd-dflash-command-audit bash deploy_pd_dflash.sh all # 新实验:八节点空闲后,入口负责启动、smoke、C1/C8、归档及清理 RUN_ID=pd-dflash-$(date +%Y%m%d-%H%M%S) bash deploy_pd_dflash.sh all ``` 本次实际分两段执行,使用同一个 Run ID: ```bash RUN_ID=pd-dflash-kvbounds1-20260831-1740 bash deploy_pd_dflash.sh all # 服务和 smoke 成功后,客户端数据集路径报错。修正挂载,不重启服务: RUN_ID=pd-dflash-kvbounds1-20260831-1740 bash deploy_pd_dflash.sh bench RUN_ID=pd-dflash-kvbounds1-20260831-1740 bash deploy_pd_dflash.sh logs RUN_ID=pd-dflash-kvbounds1-20260831-1740 bash deploy_pd_dflash.sh stop ``` `bench` 只能复用已运行且配置匹配的服务;当前服务已清理,复测应使用新 Run ID 的 `all`。正式执行用 tmux 托管同一入口,没有新增 launch 脚本。 ## 6. 原始结果与交付 601 原始目录: ```text /data/hzy/sskj/experiments/pro6000/kimi3_pro6000_pd_dflash_validation/ results/pd-dflash-kvbounds1-20260831-1740/ bench/gsm8k_c1.jsonl # 逐题输出及原始 meta_info bench/gsm8k_c8.jsonl bench/gsm8k_c1_summary.json bench/gsm8k_c8_summary.json commands/ # 8 条 docker run、Router、2 条 bench logs/p_0.log ... p_3.log # P 四节点 logs/d_0.log ... d_3.log # D 四节点 logs/router.log metadata/post_run_resources.txt # 八节点清理核验 result_validation.json # 独立答案/统计复核及证据 SHA256 ``` 本地副本:`/Users/hzy/Desktop/infra/docs/evidence/kimi_k3_pd_dflash/results/pd-dflash-kvbounds1-20260831-1740/`。轻量结果、完整服务日志与补丁随 GitLab 提交;模型与约 14GB OCI 镜像归档保留服务器,不纳入普通 Git。 首段 `exit_code=1` 如实保留,对应容器内数据集 `../` 路径错误;修复后 `bench_resume_exit_code=0`、`cleanup_exit_code=0`。失败客户端命令和日志另存为 `gsm8k_c1.dataset_path_failure.*`。此前 P 预热和混合池层范围两次失败保留独立 Run,未混入本轮评测结果。