Prhub

#41426 [XPU][MoE] Add WNA16 oracle backend for GPTQ sym-int4 (xpu_fused_moe)

原始 PR 作者 jasonboukheir 合并时间 2026-05-29 00:30 文件变更 2 提交数 3 评论 11 代码增减 +179 / -7

执行摘要

为 Intel XPU 添加 W4A16 INT4 MoE 支持

参照RFC #33214,XPU支持需要从IPEX迁移到vllm-xpu-kernels,以提升性能、可维护性和集成质量。此前已完成FP8、MXFP4等MoE支持,INT4 MoE是缺失的关键一环。同时,GPTQ量化的MoE模型(如Qwen3.6-35B-A3B-GPTQ-Int4)在XPU上无法运行,因为gptq_marlin等现有后端不支持XPU平台。本PR填补该空白。

值得精读,尤其是WNA16 oracle的可扩展设计(通过枚举和优先队列选择后端)以及XPUExpertsWNA16如何以最小改动集成到现有FusedMoE框架。关注_process_weights_xpu的布局转换逻辑和apply中的assert条件设计。

讨论亮点
  1. 依赖顺序争议:评审者jikunshang建议先完成XPU int4线性支持(PR #38288)再合入MoE部分,但作者基于已有INCXPULinearMethod推进了MoE配合,双方未进一步深入争论。
  2. INC安置位置:yiliu30建议将INC相关MoE方法放入新的inc/schemes/布局(PR #40601),作者已原型验证但最终PR未包含INC变更(按jikunshang建议revert inc.py,所有改动集中在oracle和experts两个文件)。
  3. 准确性问题:jikunshang发现对Qwen3-30B-A3B-GPTQ-Int4运行结果不准确,作者定位原因为AutoGPTQ checkpoints缺少dynamic/extra_config字段导致INC误将router (mlp.gate)也做int4量化,修复方案为仅在量化类型为int4且层名含mlp.experts时才应用MoE量化。
  4. 最终决策:评审者同意只保留oracle和xpu_moe两个文件的改动,并通过auto-merge合入。

实现拆解

  1. 扩展WNA16 oracle后端:在int_wna16.py中新增WNA16MoEBackend.XPU枚举,在backend_to_kernel_cls中添加XPU分支返回XPUExpertsWNA16;修改_get_priority_backends,使XPU平台优先返回XPU后端。
  2. 新增XPUExpertsWNA16类:在xpu_moe.py中继承XPUExperts,设置self.is_int4 = True,并覆盖_supports_quant_scheme以匹配(kInt4Static, None)。同时修改基类XPUExperts__init__增加self.is_int4 = False,在apply中添加assert确保最多一个量化标志为True,并将is_int4传递给kernel。
  3. 调整make_wna16_moe_kernel调度:在int_wna16.pymake_wna16_moe_kernel中,当experts_cls is XPUExpertsWNA16时,直接实例化并断言activation_format为Standard。
  4. 权重处理辅助函数:新增_process_weights_xpu函数,实现GPTQ格式([E, K/8, 2N] int32)到XPU kernel所需格式([E, 2N, K/2] uint8)的转换(transpose + contiguous + view(uint8))。
    本次变更未包含直接测试文件,但已在Intel Arc Pro B70上进行端到端验证。
文件 模块 状态 重要度
vllm/model_executor/layers/fused_moe/oracle/int_wna16.py MoE 调度器 modified 7.83
vllm/model_executor/layers/fused_moe/experts/xpu_moe.py MoE 专家层 modified 7.76

关键符号

_process_weights_xpu XPUExpertsWNA16.__init__ XPUExpertsWNA16._supports_quant_scheme backend_to_kernel_cls (XPU branch) make_wna16_moe_kernel (XPU branch) _get_priority_backends

关键源码片段

vllm/model_executor/layers/fused_moe/experts/xpu_moe.py data-contract

新增 XPUExpertsWNA16 类,设置 is_int4=True 并限定量化方案,同时修改基类以支持 int4 标志和 assert 检查。

# vllm/model_executor/layers/fused_moe/experts/xpu_moe.pyclass XPUExpertsWNA16(XPUExperts):
    """
    W4A16 INT4-symmetric MoE backed by xpu_fused_moe(is_int4=True).
    Weight layout: [E, 2N, K//2] uint8 (packed int4), scales [E, 2N, K//group_size] fp16.
    """
    def __init__(self, moe_config, quant_config, max_num_tokens=None, num_dispatchers=None):
        super().__init__(moe_config, quant_config, max_num_tokens, num_dispatchers)
        self.is_int4 = True # 基类中新增的标志
​
    @staticmethod
    def _supports_quant_scheme(weight_key, activation_key) -> bool:
        # 仅支持 int4 权重,无激活量化
        return (weight_key, activation_key) == (kInt4Static, None)

# XPUExperts.apply 中的 assert(新增)
def apply(self, output, hidden_states, w1, w2, topk_weights, topk_ids, ...):
    # 确保最多一个量化标志为 True,避免混淆 kernel 优先级
    assert sum([self.is_fp8, self.is_int4, self.is_mxfp4]) <= 1, (
        f"XPUExperts: at most one of is_fp8, is_int4, is_mxfp4 may be True; "
        f"got is_fp8={self.is_fp8}, is_int4={self.is_int4}, is_mxfp4={self.is_mxfp4}."
    )
    if self.fused_moe_impl is None:
        topk = topk_ids.size(-1)
        self.fused_moe_impl = XpuFusedMoe(
            w13=w1, w13_scales=self.w1_scale, w2=w2, w2_scales=self.w2_scale,
            n_experts_per_token=topk, activation=activation.value,
            num_experts=self.moe_config.num_local_experts,
            ep_rank=self.moe_config.ep_rank, ep_size=self.moe_config.ep_size,
            is_fp8=self.is_fp8, is_int4=self.is_int4, # 新传递
            is_mxfp4=self.is_mxfp4, is_mxfp8=self.is_mxfp8,
        )
    self.fused_moe_impl.apply(output=output, hidden_states=hidden_states,
                              topk_weights=topk_weights, topk_ids=topk_ids)

评论区精华

xpu int4 linear 依赖顺序 设计

jikunshang 认为应优先合入 int4 linear 支持(PR #38288)再处理 MoE,但作者选择基于已有 INCXPULinearMethod 直接推进 MoE 配合。

结论:未强制要求,最终 MoE 部分独立合入,线性支持仍在进行中。 · 已解决

INC MoE 方法放置位置 设计

yiliu30 建议将 INC 相关 MoE 方法放入新的 `inc/schemes/` 布局(PR #40601),作者已原型验证但未包含在最终 PR 中。

结论:作者同意后续 rebase 到 inc/schemes,但本 PR 仅保留 oracle 和 xpu_moe 变更。 · 已解决

准确性问题:router 权重误量化 正确性

jikunshang 报告 `Qwen3-30B-A3B-GPTQ-Int4` 推理不准确,作者定位为 AutoGPTQ checkpoint 缺少 `dynamic`/`extra_config` 导致 INC 将 router 层也做 int4 量化。

结论:修复:仅在量化类型为 int4 且层名含 `mlp.experts` 时才应用 MoE 量化,推送修复 commit 0e526e7。 · 已解决

建议还原 inc.py 改动 设计

jikunshang 认为 inc.py 还原后所有功能可集中在其他两个文件,无需额外 INC 变更。

结论:接受建议,最终 PR 仅包含 oracle 和 xpu_moe 两个文件的变更。 · 已解决

风险与影响

  1. 权重布局兼容性:GPTQ不同checkpoint可能采用不同分组大小、pack顺序,_process_weights_xpu中的固定转换(transpose(1,2).contiguous().view(torch.uint8))可能对其他模型不适用,导致推理错误。
  2. 仅INC触发XPU后端:目前XPU后端仅通过INC量化方法路由,若其他量化方法(AutoRound、compressed_tensors)也能选择XPU后端,但权重格式不匹配,可能静默失败。
  3. 缺少单元测试覆盖:两个变更文件均无新增测试,回归风险依赖集成测试。
  4. 性能边界:当前仅测试Qwen3.6-35B-A3B-GPTQ-Int4,其他模型的分组大小、专家数可能导致kernel选择不同路径,性能未验证。

用户影响:Intel XPU用户现在可以运行GPTQ-Int4量化的MoE模型(如Qwen3-30B-A3B-GPTQ-Int4),无需IPEX,端到端推理可行。
系统影响:新增一个MoE后端选择,影响MoE层初始化路径;对非XPU平台无影响(oracle优先返回CPU/CUDA后端)。
团队影响:推进了RFC #33214的int4 MoE子任务,为后续INC refactor(PR #40601)提供基础。

新后端仅 INC 触发 XPU 路径无单元测试 权重布局依赖具体检查点格式

关联 Issue

#33214 [RFC]: XPU kernel migration to vllm-xpu-kernels

完整报告

参与讨论