Prhub

#53155 [ROCm] Keep GLM-5.2 on MRV1 and disable default breakable cudagraph

原始 PR 作者 Rohan138 合并时间 2026-09-01 12:17 文件变更 2 提交数 3 评论 24 代码增减 +10 / -7

执行摘要

ROCm 修复 GLM-5.2 误入 MRV2,默认关 breakable cudagraph

PR#52861 将 DSA 模型默认路由到 V2 model runner(MRV2)与 breakable CUDA graphs,但 ROCm 排除集只覆盖了 DeepseekV32ForCausalLM / DeepseekV4ForCausalLM,漏掉了 GlmMoeDsaForCausalLM。PR body 明确指出:"GLM-5.2 (both FP8 and MXFP4) thus became the only DSA model defaulting to MRV2 + breakable cudagraph on ROCm, which regresses decode latency on gfx950 (MI355X) by ~30–37% TPOT at batch 1 in nightly perf-eval." 通过 4 组对照实验分解出 MRV2 贡献约 3.0 ms、breakable cudagraph 贡献约 1.2 ms 的回退,因此需要同时改两处才能完全恢复基线。

值得精读,尤其是负责 ROCm / model runner / 配置系统的同学。亮点在于:一是用 frozenset 常量 + lru_cache 平台查询函数集中管理平台默认行为,配合 monkeypatch 与 cache_clear() 形成低成本测试模式;二是 perf 归因方法学(4 组对照分解 MRV2 与 breakable cudagraph 各自的回退贡献)值得借鉴,避免只靠环境变量 workaround 留下约 23% 的性能缺口。同时应记录 mawong-amd 的跟进建议,在 #53712 合并后复测并考虑是否需要反转部分默认值。

讨论亮点

唯一实质性讨论来自 mawong-amd 的 Issue 评论:"Should revisit the perf numbers here after https://github.com/vllm-project/vllm/pull/53712, and maybe also let DSV4 go back on MRV2"——即 #53712 合并后需要重新评估本 PR 的 perf 结论,并可能让 DeepSeek-V4 重新回到 MRV2 路径。该建议未被深入讨论,作为后续跟进项。claude[bot] 因 fork 来源未自动审查;维护者 AndreasKaratzas 直接 APPROVED(空 body)。此外 mergify[bot] 曾提示合并冲突,作者 rebase main 后解决。

实现拆解

  1. 变更入口:vllm/config/vllm.py 顶部的平台默认配置区,包含 ROCM_DEFAULT_MRV1_ARCHITECTURES 常量与 default_breakable_cudagraph_architectures() 函数。
  2. MRV1 排除集补漏:把 GlmMoeDsaForCausalLM 加入 ROCM_DEFAULT_MRV1_ARCHITECTURES(原来只有 DeepseekV32 / DeepseekV4 两个架构)。该集合让命中架构在 ROCm 上 use_v2_model_runner 返回 False,从而留在编译过的 MRV1 路径,这是修复约 3.0 ms 回退的关键。
  3. ROCm breakable 默认全关:default_breakable_cudagraph_architectures() 的 ROCm 分支从"排除 Deepseek 两个架构"改为直接返回空集 frozenset()。原因是 gfx950 上 breakable cudagraph 对 GLM-5.2 贡献约 1.2 ms 回退,且当前 ROCm 平台没有任何架构从中受益;VLLM_USE_BREAKABLE_CUDAGRAPH=1 的 opt-in 路径保持不变。
  4. 测试同步:tests/test_config.py 更新 test_rocm_keeps_compiled_deepseek_defaults 的 docstring 与断言(纳入 GlmMoeDsaForCausalLM),并把 test_dsa_breakable_cudagraph_platform_default 参数化用例中 ("GlmMoeDsaForCausalLM", True, True) 翻转为 ("GlmMoeDsaForCausalLM", True, False)。运行方式为 pytest tests/test_config.py -k "rocm or dsa or breakable"。
  5. 验证与 CI:在 gfx950(MI355X)TP8 上用 vllm bench serve 做对照实验,median TPOT 恢复至 13.46 ms,与 #52861 之前的好基线一致;启动日志确认不再出现 Using V2 Model Runner / Breakable CUDA graph enabled;上游 CI(Buildkite #86417)与 AMD CI(#12493)通过。
文件 模块 状态 重要度
vllm/config/vllm.py 配置系统 modified 5.86
tests/test_config.py 配置测试 modified 3.99

关键符号

default_breakable_cudagraph_architectures test_rocm_keeps_compiled_deepseek_defaults test_dsa_breakable_cudagraph_platform_default

关键源码片段

vllm/config/vllm.py core-logic

核心配置逻辑所在:`ROCM_DEFAULT_MRV1_ARCHITECTURES` 补入 `GlmMoeDsaForCausalLM`,`default_breakable_cudagraph_architectures()` 在 ROCm 上改为返回空集。这两处决定了 GLM-5.2 在 ROCm 上回到编译的 MRV1 路径,并让所有架构默认不启用 breakable cudagraph,是修复 30~37% TPOT 回退的关键。

# vllm/config/vllm.py —— ROCm 平台 DSA 模型默认运行路径配置(PR#53155 之后)
​
# TODO(rocm): 这些模型在 AMD GPU 上要么不被 MRV2 支持,要么在 MRV2 下更慢。
# 命中该集合的架构在 ROCm 上会留在编译过的 MRV1 路径。
ROCM_DEFAULT_MRV1_ARCHITECTURES = frozenset(
    {
        "DeepseekV32ForCausalLM",
        "DeepseekV4ForCausalLM",
        "GlmMoeDsaForCausalLM", # PR#53155 补上漏掉的 GLM-5.2,避免其默认走 MRV2
    }
)
​
# 各平台默认启用 breakable CUDA graph 的架构名单(PR#52861 引入 DSA 路由)。
DEFAULT_BREAKABLE_CUDAGRAPH_ARCHITECTURES = frozenset(
    {
        "DeepseekV32MTPModel",
        "DeepseekV32ForCausalLM",
        "DeepseekV4ForCausalLM",
        "DeepSeekV4MTPModel",
        "Dots3NoteForCausalLM",
        "Dots3NoteMTPModel",
        "GlmMoeDsaForCausalLM",
        "HYV4ForCausalLM",
        "HYV4MTPModel",
        "InklingForCausalLM",
        "InklingForConditionalGeneration",
        "KimiK3ForConditionalGeneration",
        "KimiK3MTPModel",
        "KimiLinearForCausalLM",
        "MiniMaxM3SparseForCausalLM",
        "MiniMaxM3SparseForConditionalGeneration",
    }
)
​
​
@lru_cache
def default_breakable_cudagraph_architectures() -> frozenset[str]:
    """返回当前平台默认启用 breakable CUDA graph 的架构集合。"""
    from vllm.platforms import current_platform
​
    if current_platform.is_rocm():
        # gfx950 实测 breakable cudagraph 贡献约 1.2 ms / 请求 的回退,
        # 因此 ROCm 默认不启用任何架构;用户仍可用
        # VLLM_USE_BREAKABLE_CUDAGRAPH=1 强制开启。
        return frozenset()
    return DEFAULT_BREAKABLE_CUDAGRAPH_ARCHITECTURES
tests/test_config.py test-coverage

同步覆盖新默认行为:断言 GLM-5.2 仍在 `ROCM_DEFAULT_MRV1_ARCHITECTURES` 且不在 ROCm 的 breakable 默认集合中,并把参数化用例里 GLM 在 ROCm 上的期望值翻转为 False,防止后续回归。

@pytest.mark.parametrize(
    ("architecture", "is_rocm", "expected"),
    [
        ("DeepseekV32ForCausalLM", False, True),
        ("DeepseekV32ForCausalLM", True, False),
        ("GlmMoeDsaForCausalLM", False, True),
        # PR#53155 翻转:ROCm 上 GLM-5.2 默认不再启用 breakable cudagraph
        ("GlmMoeDsaForCausalLM", True, False),
    ],
)
def test_dsa_breakable_cudagraph_platform_default(
    monkeypatch, architecture, is_rocm, expected
):
    from vllm.config.vllm import default_breakable_cudagraph_architectures
    from vllm.platforms import current_platform
​
    monkeypatch.delenv("VLLM_USE_BREAKABLE_CUDAGRAPH", raising=False)
    monkeypatch.setattr(current_platform, "is_rocm", lambda: is_rocm)
    # 平台查询函数带 lru_cache,须清缓存才能让 monkeypatch 的平台判断生效
    default_breakable_cudagraph_architectures.cache_clear()
    config = SimpleNamespace(
        model_config=SimpleNamespace(architectures=[architecture]),
        compilation_config=CompilationConfig(),
    )
    config._uses_breakable_cudagraph_by_default = lambda: (
        VllmConfig._uses_breakable_cudagraph_by_default(config)
    )
​
    try:
        assert VllmConfig._maybe_enable_breakable_cudagraph(config) is expected
        if expected:
            assert config.compilation_config.mode == CompilationMode.NONE
    finally:
        os.environ.pop("VLLM_USE_BREAKABLE_CUDAGRAPH", None)
        default_breakable_cudagraph_architectures.cache_clear()

评论区精华

PR#53712 合并后重新评估 ROCm MRV2 性能与 DSV4 归属 question

mawong-amd 评论建议在 #53712 合并后重新审视本 PR 的 perf 数据,并考虑让 DeepSeek-V4 重新回到 MRV2 路径。

结论:本 PR 先行合并恢复基线;重新评估留待 #53712 之后跟进。 · 未解决(跟进项)

fork PR 自动 review 不可用 other

claude[bot] 说明 fork 来源的 PR 自动 review 被禁用,维护者可评论 `@claude review` 触发单次 review。

结论:AndreasKaratzas 直接 APPROVED(空 body),无实质 review 评论。 · 已解决

合并冲突与 rebase other

mergify[bot] 提示存在需要解决的合并冲突;作者 rebase main 后解决(合并提交 5037b98)。

结论:已解决,最终 head 为 5037b989070a,CI 重新跑通。 · 已解决

风险与影响

  1. ROCm 默认行为全局变更:default_breakable_cudagraph_architectures() 在 ROCm 上直接返回空集,意味着当前在 ROCm 上性能可能尚可的架构(如 KimiK3、Dots3Note、MiniMaxM3 等)也无法默认启用 breakable cudagraph,属于"一刀切"策略,后续需按架构逐个回填。
  2. 后续结论可能被推翻:mawong-amd 指出 #53712 合并后需重新评估 perf;若 #53712 改善 ROCm 上 MRV2/breakable 性能,本 PR 的部分默认值(尤其 DSV4 归属)可能需要翻转。
  3. 测试覆盖限制:作者说明 pytest 未在 perf 容器内实际执行,仅靠 CI 覆盖;tests/test_config.py 的断言依赖 lru_cache 清理(cache_clear())与 monkeypatch 模拟平台,若平台判断逻辑演进需同步维护。
  4. MRV1 编译成本:恢复 MRV1 是编译路径,可能带来更长的启动编译时间,换取运行时 TPOT 收益;对强调快速启动的场景有轻微影响。
  5. 非 ROCm 无影响:分支条件明确限定 current_platform.is_rocm(),NVIDIA/CPU 等平台不受影响。
  1. 用户侧:ROCm gfx950 上运行 GLM-5.2(FP8 / MXFP4)的用户,batch 1 decode TPOT 从 17.74 ms 回落至 13.46 ms(约 -24%),恢复至 #52861 之前的基线水平。
  2. 系统侧:ROCm 平台上所有 DSA 架构默认回到 MRV1 路径且不再默认启用 breakable cudagraph;启动日志行为随之变化。
  3. 团队侧:AMD 团队需要跟踪 #53712 合并后的 perf 复测,并决定是否让 DeepSeek-V4 / GLM-5.2 重新进入 MRV2;同时为 #41834(NVIDIA SM12x DeepSeek-V4 enablement)等后续工作提供 ROCm 对照基线。
  4. 非 ROCm:完全不受影响,这是 PR body 明确声明的设计边界。
ROCm 默认行为全局变更 配置默认值一刀切 依赖后续 PR 重新评估 真机 pytest 未在 PR 内执行

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论