GLM-5.3-NVFP4 PP+MTP verify CUDA graph 修复(r37)— 2026-09-08 @ 174.1.60.8
上一个实验(glm53_ppmtp_r36_degloo)判定:PP+MTP eager 模式正确但 MTP 机器开销吃光收益(step 239ms@cc16 vs 净胜拐点 148ms),图模式(r36g)则正确性崩溃(accept 2.85→1.05 + 数字乱码)。本实验继续修复图捕获并兑现 MTP+PP 双优势。结果:修复成功,killer e2e -40%、TPOT -40%、TTFT 近乎减半,全面胜过在役 A16 配置并留役生产。
环境
- 镜像 lmsysorg/sglang:nightly-dev-cu13-20260901-07c8f729,GLM-5.3-NVFP4,8×RTX 6000D(SM120)
- TP4PP2 + EAGLE(3 steps / topk1 / 4 draft tokens),DSA,hicache 3,memfrac 0.88,chunk 8192, --disable-overlap-schedule,SYNC_MASK=127,de-GLOO 中继(r36 遗产)
- r36 的 8 个挂载文件全部沿用 + 本实验新增第 9 挂载(decode_cuda_graph_runner)
排查过程(按时间序)
- :1515 切片修复(r33 注释的根因猜测):decode runner
execute()对非末 stage 的 PPProxyTensors 按self.bs(请求数)切片,截断 TARGET_VERIFY 树行(bs×4)→ 改按raw_num_token。必要但不充分: r37 实测 accept 仍 1.02-1.27 + 乱码(bs=1 零 padding 下确定性复现 → 排除竞态/padding)。 - 按 stage 二分:把 /root/sglang_patch2/eagle_worker_common.py 的
_PP_FORCE_EAGER_VERIFY门扩展为 1/2/3 模式(全 eager / 仅首 stage eager / 仅末 stage eager)。判决:- 模式 2(PP0 eager + PP1 图)→ 仍乱码;模式 3(PP0 图 + PP1 eager)→ 完全正确。
- 缺陷唯一在末 stage(PP1)的 verify 图;PP0 图(含 :1515 修复)被实证正确。
- 遥测(runner 内置 VRFY-IN/BUF/G/SLOT + xcheck,SGLANG_PP_SPEC_DEBUG=2/3):
- 入口 relayed hidden 每轮新鲜正常;返回 hidden_states 新鲜;logits argmax 全是高频英文 token(' of'/' the'/':', tokenizer 解码实证)→ "模型没看到上下文"signature。
- VRFY-SLOT:pp 槽位注册健康(enabled=True copy_from_fb=True buffer=静态张量 data_ptr 一致)。
- VRFY-BUF:fill_from 之后静态 pp 缓冲仍全零;VRFY-IN needs_init=False → 真凶。
根因(真·根因,取代 r33 的 :1515 猜测为唯一根因)
spec worker 的 plan-stream 在 prepare 阶段预跑 load_batch(eagle_prepare_for_verify 的 overlap 设计)——彼时
PP 中继尚未到达,pp_proxy_tensors=None,fill_from 跳过全部 pp 槽位,仅完成常规槽位 + 注意力元数据,
batch 被标记 pre-planned(needs_forward_metadata_init()=False)。前向流 execute() 于是走 pre-planned 早退路径,
该路径只补拷 input_ids/positions 两个 spec 必需字段 → pp_proxy(hidden_states/residual/topk_indices)
静态缓冲永远是分配时的全零。捕获图内的 clone kernel(run_once 体内,:1212)从静态缓冲拷零 → 末 stage 在零激活上
计算 → logits 为"无上下文"垃圾 → 全拒 + 乱码。
一切旁证自洽:
- PP0(首 stage)不吃 pp 输入(input_ids/positions 恰好是早退路径补拷的两个)→ 模式 3 正确;
- B'(nomtp+图+PP)无 spec worker plan-stream → 走完整 fill_from 路径 → 正确;
- TP8 A16 无 PP → 正确;
- 图 logits ≈ eager 参考滞后一轮(xcheck 实测):零 token 嵌入 + 上一轮 KV 历史的注意力产出。
修复(patches/decode_cuda_graph_runner_fix.py,第 9 挂载文件)
两处改动:
execute():1515:PPProxyTensors 抽取改按self.raw_num_token切(原 :bs 截断树行;decode width=1 时二者等价于 raw/padded 行数之差,树行场景必须 raw_num_token)。load_batch()pre-planned 早退路径:新增 pp_proxy 补拷——pp_proxy_tensors各 key 拷入静态缓冲[:src.shape[0]],pad 尾(self.bs*captured_req_width之外)清零保确定性。这是本修复的核心。
生产运行时遥测代码(VRFY-* / xcheck)随文件留存,由 SGLANG_PP_SPEC_DEBUG 门控(0=关闭,无开销)。
验证阶梯(全部通过)
- 质量门 7/7 ×2 boot(GSM8K×5/中文推理/tool call);
- accept 恢复 3.59-3.75(eager 档);
- conc_test ×3 ALL-OK、killer ×6 零崩溃(三个 boot 累计);
- 性能见 results/bench_results.md:vs eager -40% e2e;vs A16 在役配置 -40% e2e、TTFT 33s vs 58-61s。
生产终态
60.8 glm53-nvfp4:30000 = r37 胜者配置(verify 图 + draft eager + de-GLOO + mask127),
--restart unless-stopped,已取代 A16 留役(A16 脚本 deploy_glm53_605.sh 留盘可切回)。
draft 图(DRAFTEAGER=0)实测无增益(噪声带内互有胜负),保持 eager 以少一个变量。
遗产与提醒
- /root/sglang_patch2/eagle_worker_common.py 已被本实验覆盖为 bisect 版(md5 babb6461…):env "1"/"0" 语义与 r36 版完全兼容,新增 "2"/"3" 单侧模式;r36 档案中的旧 md5 以本目录为准。
- 语料池 61,772 token 剩余(< 一次 i8k 262,144),i8k 永久无重跑余量,killer random-ids 为标准口径。
- killer 的 raw bench JSON(/data/hf_models/bs_results/san_cc16_s*.json)被 A16 复测覆盖, 胜者数字以 results/bench_results.md 记录为准。