Prhub

#44849 [ROCm][MiniMax-M2] Dispatch fused QK-norm + AllReduce via AITER

原始 PR 作者 akii96 合并时间 2026-07-14 11:10 文件变更 1 提交数 7 评论 20 代码增减 +12 / -0

执行摘要

MiniMax-M2 融合 QK-norm+AllReduce ROCm 路径

该 PR 的目的是利用 AMD AITER 库的 fusion 内核进一步提升 MiniMax-M2 在 ROCm 上的推理性能。PR body 中提供的基准测试显示输出 token/s 提升 14.7%,中位 TPOT 降低 16.4%。关联的 AITER issue ROCm/aiter#3163 提到该 fusion 可带来约 30% 的端到端提升。

该 PR 设计清晰,值得关注其简洁的 dispatch 模式和 review 中讨论的“快速失败”哲学。对于其他需要为特定硬件添加融合内核的开发者有参考价值。建议精读以理解如何安全地集成第三方 kernel 库。

讨论亮点
  • Rohan138 建议将 custom_fused_qknorm_ar 的可用性检查移到 rocm_aiter_ops 中,并加上 TODO 以便后续移除。作者照做。
  • BadrBasowid 指出 _get_aiter_custom_all_reduce 包装器是冗余的,可以直接调用 rocm_aiter_ops.get_aiter_allreduce()。作者移除该包装器。
  • tjtanaa 和 Rohan138 坚持去掉 try/except,认为如果 AITER API 变化应该直接报错,而不是静默回退导致难以调试。作者接受并移除了 try/except。

实现拆解

  1. 导入 AITER 模块:在文件开头添加 from vllm._aiter_ops import rocm_aiter_ops。
  2. 新增 AITER 分支:在 _minimax_qk_norm_fusion 函数中,既有的 C++ custom op 路径之后,添加一个针对 AITER 的新分支。
  3. 维度对齐检查:计算 warp_work_size = 32 * (16 // element_size),只有当 q_size 和 kv_size 都能被 warp_work_size 整除时才进入 AITER 路径,否则回退以避免 kernel 断言失败。
  4. 调用融合 kernel:通过 rocm_aiter_ops.get_aiter_allreduce().aiter_ca.custom_fused_qknorm_ar 执行融合的 QK-norm + AllReduce。
  5. 兜底回退:若条件不满足或 AITER 不可用,则调用原有的 _minimax_qk_norm_tp_fallback。
  6. Review 精简:经讨论移除了 runtime probe、冗余包装器和 try/except,使代码更简洁,并确保 AITER API 变更时直接暴露错误。
文件 模块 状态 重要度
vllm/model_executor/layers/minimax_rms_norm/rms_norm_tp.py 模型层 modified 6.35

关键符号

_minimax_qk_norm_fusion

关键源码片段

vllm/model_executor/layers/minimax_rms_norm/rms_norm_tp.py core-logic

核心修改文件:添加 AITER 融合 QK-norm+AllReduce 的分支路径

def _minimax_qk_norm_fusion(
    qkv: torch.Tensor,
    q_weight: torch.Tensor,
    k_weight: torch.Tensor,
    q_size: int,
    kv_size: int,
    tp_rank: int,
    tp_world: int,
    eps: float,
    workspace: torch.Tensor | None,
) -> tuple[torch.Tensor, torch.Tensor]:
    '融合 QK-norm + AllReduce,优先使用 AITER 内核,否则回退。'
    assert qkv.ndim == 2
    num_tokens = qkv.shape[0]
​
    # 原有路径:通过 C++ custom op 的 Lamport fused allreduce+RMSNorm
    if (
        workspace is not None
        and tp_world > 1
        and num_tokens <= MINIMAX_QK_NORM_MAX_TOKEN_NUM
        and _MINIMAX_FUSED_AR_RMS_QK is not None
    ):
        return _MINIMAX_FUSED_AR_RMS_QK(
            qkv, q_weight, k_weight, workspace,
            q_size, kv_size, tp_rank, tp_world, eps,
        )
​
    # 新路径:ROCm AITER 融合 QK-norm + AllReduce
    if tp_world > 1 and num_tokens <= MINIMAX_QK_NORM_MAX_TOKEN_NUM:
        pack_size = 16 // qkv.element_size() # AITER 数据包大小
        warp_work_size = 32 * pack_size # warp 粒度,通常为 256 或 512
        # 只处理维度对齐的形状,避免 AITER 内部断言失败
        if q_size % warp_work_size == 0 and kv_size % warp_work_size == 0:
            aiter_ar = rocm_aiter_ops.get_aiter_allreduce()
            if aiter_ar is not None:
                q_out, k_out, _ = aiter_ar.aiter_ca.custom_fused_qknorm_ar(
                    qkv, q_weight, k_weight, eps
                )
                return q_out, k_out
​
    # 兜底:顺序执行 RMSNorm + AllReduce(Triton 实现)
    return _minimax_qk_norm_tp_fallback(
        qkv, q_weight, k_weight, q_size, kv_size, tp_rank, tp_world, eps
    )

评论区精华

将 custom_fused_qknorm_ar 检查移到 rocm_aiter_ops 设计

Rohan138 建议将自定义 fused QK-norm 的可用性检查放到 rocm_aiter_ops 中,避免散落在各层模块,并添加 TODO 以便后续 AITER 版本升级后移除。

结论:作者按建议移动了函数,并添加了 TODO 注释,后续 AITER v0.1.16 后移除了该 probe。 · 已解决

移除冗余的 _get_aiter_custom_all_reduce 包装器 style

BadrBasowid 指出该包装器是多余的,可以直接使用 rocm_aiter_ops.get_aiter_allreduce()。

结论:作者移除了包装器,直接调用。 · 已解决

去掉 try/except 使 AITER 错误暴露 正确性

tjtanaa 认为如果 AITER API 变化,应该直接抛出异常,而不是用 try/except 静默回退,否则很难调试。Rohan138 赞同。

结论:作者删除 try/except,让任何 AITER 调用失败直接报错。 · 已解决

风险与影响

  • 缺少测试覆盖:该 PR 没有新增测试,可能存在回归风险。
  • ROCm 平台特异性:路径仅在 rocm_aiter_ops.is_enabled() 时触发,其他平台不受影响,但可能缺乏跨平台测试。
  • 依赖 AITER 版本:依赖 AITER >= v0.1.16.post2,若后续 API 变动,由于去掉了 try/except,会直接崩溃,但这是有意设计。
  • 维度对齐检查:对齐条件可能过于严格,导致某些合法形状回退,但仅影响性能不影响正确性。
  • 对 ROCm + MiniMax-M2 用户:显著性能提升,无功能变化,回退机制保证不会 break。
  • 对其他平台/模型:无影响,路径被 rocm_aiter_ops 和硬件品牌保护。
  • 对维护团队:需跟踪 AITER 版本,以及该路径是否与其他 AITER 用法保持一致。
缺少测试覆盖 ROCm 平台特异性 依赖 AITER 版本

关联 Issue

#3163 minimax ops: support fused qknorm+allreduce kernel
#3189 [custom_all_reduce] qknorm_allreduce_fusion_kernel_2stage: grid-strided loop, drop 80-token cap

完整报告

参与讨论