Prhub

#39547 [AMD][bugfix] Fix DSV4 MTP crash

原始 PR 作者 RolaoDenthu 合并时间 2026-09-16 12:10 文件变更 1 提交数 1 评论 0 代码增减 +3 / -0

执行摘要

修复 AMD 上 DSV4 MTP 崩溃,用 is_dspark 门控 D2H 优化

PR body 明确指出:#39116 crashes DSV4 on AMD when MTP is on with GPU memory access fault. The commit drop a D2H sync in repeat_interleave. 也就是说 #39116 为性能去掉了 repeat_interleave 路径中的 D2H 同步,但该同步在 AMD + MTP 的 EAGLE verify 流程中是正确性前提。修复策略不是整体回滚,而是用 is_dspark 把优化 gate 起来:dspark 平台保留性能优化,其余平台恢复同步。

不值得精读,但值得记录。它展示了性能优化遭遇平台差异时的一种最小成本处理方式:不整体回滚,而是用 is_dspark 将优化限定在已知安全的平台。对 AMD 后端维护者而言,建议确认 is_dspark 覆盖了实际崩溃环境,并考虑补充自动化测试,防止回归。

讨论亮点

这个 PR 几乎没有实质讨论(comments 0、review comments 0)。唯一的 review 来自合并者 HaiShaw:LGTM. HIP specific.,表明维护者认可修复范围被严格限定在 HIP 后端。可提炼的隐含结论是:D2H 同步不是可以随便移除的性能细节,它在 AMD + EAGLE verify 路径上是正确性前提;平台差异需要显式 gate,而非隐式假设。

实现拆解

  1. 变更入口:python/sglang/srt/layers/attention/deepseek_v4_backend_hip_radix.py 中的 init_forward_metadata_target_verify_old。这是 DSV4 在 HIP/radix 后端为 target verify(MTP/EAGLE 式验证)构建 prefill metadata 的入口,函数先根据 ragged_layout 是否存在区分 graph 与 eager 两条路径,分别计算 num_tokens 与 exact_num_tokens。
  2. 核心改动:在调用 init_forward_metadata_prefill 之前插入一行赋值 exact_num_tokens = exact_num_tokens and self.is_dspark。exact_num_tokens 为 True 时,下游 prefill-meta 构建会通过 output_size 跳过原本隐含在 sum() 中的 D2H 同步;而 AMD 上 EAGLE verify 缺少这次同步会触发 GPU 内存访问错误。因此用 is_dspark 作为显式平台开关:只有已知安全的平台保留跳同步优化,其它平台强制走带 D2H 同步的保守路径。
  3. 测试配套:本次没有新增单元测试文件,PR body 提供 gsm8k 准确率(1319: 0.952)作为模型输出质量验证;reviewer HaiShaw 仅给出 LGTM. HIP specific.,确认变更范围仅在 HIP 后端内。
文件 模块 状态 重要度
python/sglang/srt/layers/attention/deepseek_v4_backend_hip_radix.py 注意力后端 modified 4.99

关键符号

init_forward_metadata_target_verify_old

关键源码片段

python/sglang/srt/layers/attention/deepseek_v4_backend_hip_radix.py core-logic

DSV4 在 HIP/radix 后端上构建 target verify(MTP)prefill metadata 的唯一修改点;用 is_dspark 门控 exact_num_tokens,决定是否跳过 D2H 同步。

# 函数:init_forward_metadata_target_verify_old
# DSV4 HIP/radix 后端构建 target verify(MTP)prefill metadata 的入口。
# 下方片段展示 ragged / eager 两条路径的 num_tokens 计算,
# 以及本次新增的 is_dspark 门控(片段末尾 3 行)。
if ragged_layout is not None:
    extend_start_loc = ragged_layout.extend_start_loc.to(
        device=seq_lens.device, dtype=torch.int32
    )
    extend_seq_lens = verify_lens_dev
    seq_lens = seq_lens + verify_lens_dev.to(seq_lens.dtype)
    # 总 verify token 数:graph 路径由 padded layout 给出
    # total_verify_tokens(tier 大小),eager 路径则回退到
    # sum(verify_lens) 得到真实总数。
    num_tokens = ragged_layout.total_verify_tokens
    if num_tokens is None:
        num_tokens = int(verify_lens_dev.sum().item())
        exact_num_tokens = True
    else:
        num_tokens = int(num_tokens)
        # padded tier:num_tokens 大于等于 sum(verify_lens)
        exact_num_tokens = False
    extend_seq_lens_cpu = None
    seq_lens_cpu = None
else:
    seq_lens = seq_lens + self.target_verify_num_draft_tokens
    seq_lens_cpu = [
        x + self.target_verify_num_draft_tokens for x in seq_lens_cpu
    ]
    extend_seq_lens_cpu = [self.target_verify_num_draft_tokens] * batch_size
    num_tokens = self.target_verify_num_draft_tokens * batch_size
    extend_seq_lens = self._move_to_device(extend_seq_lens_cpu)
    exact_num_tokens = True
​
if out_cache_loc is None:
    out_cache_loc = seq_lens.new_zeros(num_tokens)
​
# output_size 会跳过 prefill-meta 构建中隐含的 sum() 的 D2H 同步;
# EAGLE verify(MTP)缺少该同步会在 AMD 上触发 GPU 内存访问错误,
# 因此只在 is_dspark 平台保留该优化,其余平台强制走带同步的路径。
exact_num_tokens = exact_num_tokens and self.is_dspark
return self.init_forward_metadata_prefill(
    max_seq_len=max_seq_len,
    req_pool_indices=req_pool_indices,
    seq_lens=seq_lens,
    seq_lens_cpu=seq_lens_cpu,
    out_cache_loc=out_cache_loc,
    num_tokens=num_tokens,
    extend_seq_lens=extend_seq_lens,
    extend_seq_lens_cpu=extend_seq_lens_cpu,
    need_compress=True,
    use_prefill_cuda_graph=use_prefill_cuda_graph,
    compress_gpu_plan=ragged_layout is not None,
    extend_start_loc=extend_start_loc,
    attach_decode_streams=True,
    exact_num_tokens=exact_num_tokens,
)

评论区精华

HIP specific 修复范围确认 设计

HaiShaw 在最终审核中仅评论 LGTM. HIP specific.,确认该变更只作用于 HIP 后端路径,不涉及 CUDA 等其它后端。

结论:维护者确认修复范围安全,直接合并,无后续修改要求。 · 已解决

风险与影响

风险点有三处值得关注:

  • is_dspark 判定本身决定修复是否覆盖崩溃场景:若崩溃同样发生在 is_dspark=True 的 DSPark 环境,这行门控不会恢复同步,问题会残留。PR body 未给出复现环境的 is_dspark 取值,需要维护者确认。
  • 非 dspark 的 AMD 平台会放弃 #39116 的 D2H 优化,恢复到带同步的旧路径,prefill metadata 构建有一定性能回退,这是正确性优先的有意取舍。
  • 没有自动化回归测试。exact_num_tokens 语义微妙(graph padded tier 与 eager 精确值),未来任何重构或平台扩展都可能再踩同样问题,建议后续补一个 AMD + MTP 的注册测试。

直接受益者是 AMD + DSV4 + MTP 组合的用户,崩溃消除。该 backend 是 AMD 专属(hip_radix),CUDA 路径完全不受影响,影响面窄。对系统而言,D2H 同步行为开始按平台分化,is_dspark 实质上成为正确性相关的平台能力标志;后续在 HIP 上做同类优化时也必须带同样门控。对团队而言,需要固化这一认知,避免后续优化再次无条件移除同步。

平台门控依赖 is_dspark 判定 缺少自动化测试 非 dspark 平台性能回退

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论