Prhub

#26238 refactor(dsv4): route MHC prenorm through DeepGEMM wrapper

原始 PR 作者 YAMY1234 合并时间 2026-05-28 08:45 文件变更 6 提交数 1 评论 5 代码增减 +67 / -148

执行摘要

将 MHC prenorm 内核接入通用 DeepGEMM wrapper/warmup 路径

PR body: 'Route the DeepSeek V4 MHC prenorm DeepGEMM kernel through the common DeepGEMM wrapper entrypoint so it can share the same wrapper/warmup infrastructure as other DeepGEMM kernels.' 以及 Fridge003 在评论中要求 revert #25810 中不需要的预热变更。

对于 DeepSeek V4 和 DeepGEMM wrapper 的维护者值得精读,了解如何将新内核类型接入统一预热框架。建议后续追踪吞吐下降原因,并考虑是否调整为与主基线一致的预热策略。

讨论亮点

Fridge003 在 Issue 评论中要求回退 #25810 的模型级预热变更:'Please revert the changes in #25810, since they are not needed'。作者确认已 revert,并重新运行 GSM8K 测试,结果在 PR body 中展示。无其他审查评论。

实现拆解

  1. 添加内核类型枚举与工厂映射:在 compile_utils.pyDeepGemmKernelType 枚举中增加 TF32_HC_PRENORM_GEMM 值,并在 _BaseWarmupExecutor.create 的字典中添加到 _TF32HcPrenormWarmupExecutor 的映射。
  2. 实现预热执行器:新增 _TF32HcPrenormWarmupExecutor 类,__init__ 中预分配 bf16 输入张量 xfp32 权重 fn,并根据 num_splits 决定是否分配分块输出;execute 方法调用 deep_gemm.tf32_hc_prenorm_gemm 并传递正确维度的张量。同时更新 get_memory_requirement 以正确估计该内核的内存需求。
  3. 新增包装函数:在 entrypoint.py 中添加 tf32_hc_prenorm_gemm 函数,通过 deep_gemm_execution_hook 包装对底层 deep_gemm.tf32_hc_prenorm_gemm 的调用,并处理 m=0 的空输入情况。
  4. 路由调用点:在 deepseek_v4.pyhc_pre 方法和 mhc.pymhc_pre 函数中,将原来的 import deep_gemm; deep_gemm.tf32_hc_prenorm_gemm(...) 替换为从 entrypoint 导入 tf32_hc_prenorm_gemm 并调用,同时修正参数命名(从 num_splits= 改为 n_splits)。
  5. 清理模型级预热代码:删除 deepseek_v4.py 中的 prewarm_mhc_token_countsprewarm_mhc_token_count_buckets 方法,以及 deepseek_v4_nextn.py 中的对应委托方法;在 model_runner.pykernel_warmup 中移除对模型 kernel_warmup 钩子的调用,因为预热现在统一由 DeepGEMM wrapper 管理。
文件 模块 状态 重要度
python/sglang/srt/models/deepseek_v4.py 主模型 modified 8.56
python/sglang/srt/layers/deep_gemm_wrapper/compile_utils.py 预热工具 modified 7.8
python/sglang/srt/layers/mhc.py MHC 内核 modified 6.91
python/sglang/srt/layers/deep_gemm_wrapper/entrypoint.py 入口包装 modified 6.76
python/sglang/srt/model_executor/model_runner.py 运行器 modified 6.13
python/sglang/srt/models/deepseek_v4_nextn.py 推测模型 modified 5.95

关键符号

tf32_hc_prenorm_gemm _TF32HcPrenormWarmupExecutor.__init__ _TF32HcPrenormWarmupExecutor.execute hc_pre mhc_pre kernel_warmup

关键源码片段

python/sglang/srt/layers/deep_gemm_wrapper/compile_utils.py core-logic

新增 TF32_HC_PRENORM_GEMM 内核类型和专门的 _TF32HcPrenormWarmupExecutor,扩展了 DeepGEMM 的预热基础设施。

# compile_utils.py: 新内核类型注册与预热执行器
class DeepGemmKernelType(IntEnum):
    TF32_HC_PRENORM_GEMM = auto() # 新增:MHC prenorm GEMM 内核class _TF32HcPrenormWarmupExecutor(_BaseWarmupExecutor):
    def __init__(self, max_m, n, k, num_groups):
        self.x = torch.empty((max_m, k), device='cuda', dtype=torch.bfloat16)
        self.fn = torch.empty((n, k), device='cuda', dtype=torch.float32)
        self.n = n
        self.num_splits = num_groups if num_groups > 0 else None
​
    def execute(self, m):
        if self.num_splits is None:
            out = torch.empty((m, self.n), device='cuda', dtype=torch.float32)
            sqrsum = torch.empty((m,), device='cuda', dtype=torch.float32)
        else:
            out = torch.empty((self.num_splits, m, self.n), device='cuda', dtype=torch.float32)
            sqrsum = torch.empty((self.num_splits, m), device='cuda', dtype=torch.float32)
        deep_gemm.tf32_hc_prenorm_gemm(self.x[:m], self.fn, out, sqrsum, num_splits=self.num_splits)

评论区精华

回退 #25810 的预热变更 设计

Fridge003 要求在 PR 中回退 #25810 引入的模型级 MHC token-count 预热,因为它不再需要。

结论:作者已回退,并将 PR 聚焦在路由内核到通用 wrapper。 · 已解决

风险与影响

  1. 精度与性能退化:GSM8K 分数下降 0.5%,吞吐下降约 11%,虽然可能是由于预热路径变化,但需要确认是否影响生产部署。
  2. 首次推理延迟风险:移除了模型级明确预热后,若 wrapper 的 warmup 未能覆盖所有 token count 范围,可能在首次遇到新分桶时触发即时编译,增加延迟。
  3. 代码回归:重构涉及多层调用关系,错误的路由可能导致 num_splits 参数传递错误(例如命名不匹配),但从 patch 看已修正。

影响范围限于 DeepSeek V4 模型及相关组件。用户无感知,API 未变化。内部架构统一有利于维护和扩展。性能略有下降需关注,但功能正确性保持。

精度下降待确认 移除模型级预热风险 首次运行延迟可能增加

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论