Prhub

#2047 fix glm47-flash: use paged MLA prefill on B200

原始 PR 作者 guapisolo 合并时间 2026-08-03 10:38 文件变更 2 提交数 3 评论 1 代码增减 +13 / -6

执行摘要

B200 上 GLM-4.7-Flash 改用 paged MLA prefill 修复 rollout

PR body 明确描述症状:B200 rollout prefill 失败,报错 Unsupported head dimensions: head_dim_qk=256, head_dim_vo=256。根因是 flashinfer_mla_backend.py 在 SM100 上选择了 ragged CUTLASS prefill 路径,而 fmha_cutlass_sm100.cu 不支持 256 维 QK 和 value head。修复目标是让 GLM-4.7-Flash 在 B200 上开箱可用,同时不改变 GPU 拓扑。

值得一读,但主要是启动器层面的硬件适配,不需要深挖核心库。可关注两个设计点:一是用「launcher 参数按硬件分支」而非改核心 backend 来规避硬件兼容问题,保持了核心库的整洁;二是显式保留 sglang_attention_backend 透传口子,给用户留了绕过默认路径的逃生舱。后续建议在 sglang 升级时重点回归 B200 的 MLA prefill 路径。

讨论亮点

reviewer yueming-yuan 快速 approve,并提出 nit:"i think we might not need test for scripts args, given we will only edit it intentionally"。这与提交历史中删除 launcher 参数测试文件的 commit 完全对应,说明团队默认 scripts/ 下的启动器参数属于有意维护的配置,不为它背书自动化测试。

实现拆解

  1. 扩展参数模型:在 scripts/run_glm47_flash.pyScriptArgs 中将 hardwareLiteral["H200"] 扩展为 Literal["H200", "B200"],默认仍为 H200;新增 sglang_attention_backend: str | None = None,允许显式指定 SGLang attention backend。
  2. 按硬件差异化 rollout 并行度sglang_args 中的 --rollout-num-gpus-per-engine 由固定值 4 改为 2 if args.hardware == "B200" else 1。原因是 GLM-4.7-Flash 有 20 个 attention head,rollout TP 必须整除 20;且 B200 上需要 TP2 配合 paged MLA 路径。注意 H200 的默认值从 4 变为 1,这会改变 H200 上的推理吞吐表现。
  3. 条件追加 SGLang flag:当 sglang_attention_backendNone 且非 default 时透传 --sglang-attention-backend;当 hardware == "B200" 且 backend 为自动选择、defaultflashinfer 时追加 --sglang-flashinfer-mla-disable-ragged,从而避开 SM100 ragged kernel。显式选择 Triton 等其它 backend 时不会追加该 flag。
  4. 文档同步docs/models/glm/glm4-7-flash.md 更新 launcher 默认值说明,明确默认 hardware=H200、新增 sglang_attention_backend=None,并说明 B200 用 --rollout-num-gpus-per-engine 2、H200 用 1。
  5. 测试配套:第三个 commit 删除了一个专用的 launcher 参数测试文件,理由是脚本参数是刻意维护的,单测收益有限;最终只靠双 B200 端到端冒烟验证(跑到首个 optimizer step)。没有新增自动化测试。
文件 模块 状态 重要度
scripts/run_glm47_flash.py 启动脚本 modified 5.99
docs/models/glm/glm4-7-flash.md 模型文档 modified 2.23

关键符号

ScriptArgs execute

关键源码片段

scripts/run_glm47_flash.py core-logic

启动器核心改动所在:扩展 hardware 支持 B200、按硬件设置 rollout TP、条件追加 `--sglang-flashinfer-mla-disable-ragged` 以绕过 SM100 ragged kernel 限制。

"""GLM-4.7-Flash 启动器:B200 上强制走 paged MLA prefill。"""from dataclasses import dataclass
from typing import Literalimport miles.utils.external_utils.command_utils as U
​
​
@dataclass
class ScriptArgs(U.ExecuteTrainConfig):
    # 只有 H200/B200 两个合法值,默认仍是 H200,保持旧行为。
    hardware: Literal["H200", "B200"] = "H200"
    # 允许用户显式选择 SGLang attention backend,None 表示交给 SGLang 自动选。
    sglang_attention_backend: str | None = None
​
​
def execute(args: ScriptArgs):
    # GLM-4.7-Flash 有 20 个 attention head,rollout TP 必须整除 20。
    # B200 上用 TP2 配合 paged MLA prefill;H200 上保持 TP1 以换取吞吐。
    sglang_args = (
        f"--rollout-num-gpus-per-engine {2 if args.hardware == 'B200' else 1} "
        "--sglang-mem-fraction-static 0.7 "
        "--sglang-speculative-algorithm EAGLE "
        "--sglang-speculative-num-steps 2 "
        "--sglang-speculative-eagle-topk 1 "
        "--sglang-speculative-num-draft-tokens 3 "
        "--use-rollout-routing-replay "
    )
​
    # 显式指定非默认 backend 时透传,方便用户切到 Triton 等替代实现。
    if args.sglang_attention_backend not in (None, "default"):
        sglang_args += f"--sglang-attention-backend {args.sglang_attention_backend} "
​
    # B200 上 FlashInfer 的 SM100 ragged prefill kernel 不支持 head_dim=256 的
    # QK 与 VO,只有自动选择 / 默认 /flashinfer 三种情况才需要禁用 ragged 路径;
    # 若用户显式选了其它 backend(如 Triton),则无需追加该 flag。
    if args.hardware == "B200" and args.sglang_attention_backend in (None, "default", "flashinfer"):
        sglang_args += "--sglang-flashinfer-mla-disable-ragged "

评论区精华

是否需要为 scripts 启动器参数编写测试 测试

reviewer yueming-yuan 在 approve 时提出 nit:"i think we might not need test for scripts args, given we will only edit it intentionally",认为脚本参数属于刻意维护的配置,不必写专属测试。

结论:作者采纳该建议,在后续 commit 中删除了专用的 launcher 参数测试文件,只保留双 B200 运行时冒烟验证。 · 已解决

风险与影响

  1. H200 并行度变化:patch 中 --rollout-num-gpus-per-engine 从固定 4 改为 H200=1、B200=2,PR body 声称 "node8/TP4/EP8/rollout4 remain",但与最终实现并不完全吻合,H200 的 rollout 引擎数实际从 4 降到 1,可能影响 H200 推理吞吐,文档未量化该影响。
  2. 缺少自动化测试:提交中删除了唯一的参数测试,且没有新增针对 --sglang-flashinfer-mla-disable-ragged 的校验,回归只能靠手动冒烟。
  3. 依赖 SGLang 内部 flag--sglang-flashinfer-mla-disable-ragged 是 SGLang 侧面暴露的开关,后续升级 sglang(本仓库常有此类升级,如 PR#1795)时若 flag 改名或默认行为变化,B200 路径可能再次失效。
  4. 魔法字符串硬件分支hardware == "B200" 的硬编码在脚本内,未来新增其它 GPU 型号时容易遗漏条件组合。

影响范围局限于 scripts/run_glm47_flash.py 启动器和对应文档页。受益方是在 B200 上运行 GLM-4.7-Flash 训练的团队,从「完全跑不起来」变为「可端到端跑到 optimizer step」;H200 用户行为路径保持不变,但 rollout 并行度有变化,需要观察吞吐表现。对 miles 核心库、session、router 等模块零影响,团队协作上也没有引发争议。

硬件硬编码分支 缺少自动化测试 H200 默认并行度变更 依赖 SGLang 内部 flag

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论