Prhub

#28520 [AMD] Fix deepseek-v4 mtp accept length issue

原始 PR 作者 1am9trash 合并时间 2026-06-18 02:13 文件变更 3 提交数 3 评论 2 代码增减 +249 / -7

执行摘要

修复 DeepSeek-V4 MTP 接受长度下降至 ~2.17 的问题

PR 描述指出 unified_kv_triton 后端的平均接受长度仅 2.17,而 triton 后端为 3.04,导致 decode 吞吐严重受损。定位为 SWA 环写入位置缓存未考虑多步 draft decode,导致每步写入同一环槽,破坏 draft chain(token 2 后接受率骤降)。

建议阅读 get_unified_swa_loc 的修改(约 15 分钟),理解如何在保留缓存性能的同时检测变长多步场景。集成测试和 CI 配置可作为类似问题的测试范例。

讨论亮点

代码审查未引发技术讨论,维护者 HaiShaw 直接批准。Gemini Code Assist 的自动评论未提供实质性反馈。

实现拆解

  1. 问题定位与修改:在 python/sglang/srt/layers/attention/deepseek_v4_backend_hip_radix.pyget_unified_swa_loc 方法中,添加 is_multistep_draft_decode 标志,当处于 decode 模式且 speculative_num_steps > 1 时,绕过缓存,从实时 positions 重新计算环位置。
  2. 保持快速路径:对非多步 draft 路径(prefill、extend、单步 decode)仍使用缓存,避免计算开销。
  3. 新增集成测试:创建 test/registered/amd/test_deepseek_v4_pro_fp4_mtp.py,包含 GSM8K 精度测试和 MTP 接受长度测试,在 8-GPU MI35x 上验证两种后端。
  4. CI 配置:在 .github/workflows/nightly-test-amd-rocm720.yml 添加 nightly-8-gpu-mi35x-deepseek-v4-pro-mtp-rocm720 作业,分别以 unified_kv_tritontriton 后端运行测试。
文件 模块 状态 重要度
python/sglang/srt/layers/attention/deepseek_v4_backend_hip_radix.py 注意力后端 modified 6.52
test/registered/amd/test_deepseek_v4_pro_fp4_mtp.py 集成测试 added 7.35
.github/workflows/nightly-test-amd-rocm720.yml CI 配置 modified 4.1

关键符号

get_unified_swa_loc TestDeepseekV4ProFp4MTP.setUpClass TestDeepseekV4ProFp4MTP.test_a_gsm8k TestDeepseekV4ProFp4MTP.test_b_bs_1_speed

关键源码片段

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

核心修复文件,修改了 get_unified_swa_loc 方法,添加多步 draft decode 检测。

def get_unified_swa_loc(self, forward_batch: ForwardBatch) -> torch.Tensor:
    """SWA ring write target for unified_kv, shared by all layers.
    ...
    """
    positions = forward_batch.positions
    core = getattr(self.forward_metadata, "core_attn_metadata", None)
    unified = getattr(core, "unified", None) if core is not None else None
    cached = unified.swa_loc if unified is not None else None
    # 新增检测:多步 draft decode 时绕过缓存
    is_multistep_draft_decode = (
        forward_batch.forward_mode.is_decode_or_idle()
        and self.speculative_num_steps > 1
    )
    if (
        cached is not None
        and not forward_batch.forward_mode.is_idle()
        and cached.shape[0] == positions.shape[0]
        and not is_multistep_draft_decode
    ):
        result = cached
    else:
        ring = self.token_to_kv_pool.unified_swa_ring_size
        req_slot = forward_batch.req_pool_indices.to(torch.int64)
        if req_slot.shape[0] != positions.shape[0]:
            req_slot = req_slot.repeat_interleave(
                positions.shape[0] // req_slot.shape[0]
            )
        result = (req_slot * ring + positions.to(torch.int64) % ring).to(torch.int32)
    return result

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

主要风险在 is_multistep_draft_decode 检测条件若存在边界情况(如 idle 模式误判)可能导致性能回退,但不影响正确性。修改仅影响 unified_kv_triton 后端,对 triton 后端和其他模型无影响。测试覆盖 two 种后端,回归风险较低。

对 AMD 平台 DeepSeek-V4 MTP 用户:接受长度从 2.17 提升至 3.08,总 token 吞吐从 6355.88 增至 7324.37 tok/s(+15%)。新增 CI 套件防止后续回归。团队获得一个清晰的缓存绕过模式,可供其他多步 draft 场景参考。

AMD 专属变更 核心路径变更 已添加测试覆盖

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论