执行摘要
- 一句话:修复 Qwen3.5 MTP 丢弃融合共享专家权重的问题
- 推荐动作:值得精读,该 PR 展示了如何处理共享专家融合带来的权重布局变化,以及如何保持与主模型逻辑的一致性。关注其对
qwen3_5.py 的镜像逻辑和未来可能需要的扩展。
功能与动机
自 #33889 起,Qwen3.5 MXFP4 模型在 MI355X 上使用 MTP 投机解码时吞吐量下降约 12%。原因是 MTP 草稿模型在加载时未包含共享专家权重。由于 #33889 将共享专家融合的决策从全局覆盖改为按 runner 独立决策,草稿模型开始首次触发融合,但 MTP 加载器未适配,导致共享专家权重被静默跳过。本 PR 旨在修复此问题,使草稿模型能够正确加载融合后的共享专家权重。
实现拆解
- 引入平台与开关变量:在
qwen3_5_mtp.py 顶部新增 _is_hip = is_hip() 和 _use_aiter = get_bool_env_var("SGLANG_USE_AITER") and _is_hip,用于确定是否启用共享专家融合逻辑。
- 计算融合专家数量:在
load_weights 方法中,遍历模型的模块,查找 num_fused_shared_experts 属性,若存在则将其赋值给局部变量 num_fused_shared_experts,该数值表示融合的共享专家数量,这些专家被放置在路由专家槽位 num_experts 之后。
- 调整专家映射大小:将
expert_params_mapping 的 num_experts 参数改为 num_experts + num_fused_shared_experts,使得映射能够包含融合专家槽位。
- 重写权重名称:在
load_fused_expert_weights 中,当 _use_aiter 且 num_fused_shared_experts > 0 时,将 mlp.shared_expert. 前缀的重命名为 mlp.experts.{num_experts}.,以便权重加载到正确的槽位。该逻辑仅在启用融合时生效,非融合配置下保持原行为。
关键文件:
python/sglang/srt/models/qwen3_5_mtp.py(模块 模型加载;类别 source;类型 data-contract): 核心修复文件,修改了 MTP 加载器以识别融合共享专家并正确加载权重。
关键符号:load_weights, load_fused_expert_weights
关键源码片段
python/sglang/srt/models/qwen3_5_mtp.py
核心修复文件,修改了 MTP 加载器以识别融合共享专家并正确加载权重。
# python/sglang/srt/models/qwen3_5_mtp.py
# 判断是否使用 aiter,仅 AMD 平台启用共享专家融合逻辑
_is_hip = is_hip()
_use_aiter = get_bool_env_var("SGLANG_USE_AITER") and _is_hip
def load_weights(self, weights, is_mtp=False):
# ...
num_experts = getattr(self.config, "num_experts", None)
# 融合的共享专家会被放入额外的路由槽位 num_experts
num_fused_shared_experts = 0
if _use_aiter:
for module in self.modules():
fused = getattr(module, "num_fused_shared_experts", 0)
if fused:
num_fused_shared_experts = fused
break
if num_experts is not None:
# 将映射大小扩展到包含融合专家,否则共享专家权重会找不到匹配
expert_params_mapping = FusedMoE.make_expert_params_mapping(
ckpt_gate_proj_name="gate_proj",
ckpt_down_proj_name="down_proj",
ckpt_up_proj_name="up_proj",
num_experts=num_experts + num_fused_shared_experts,
)
# ...
def load_fused_expert_weights(self, name, loaded_weight):
# ...
if _use_aiter and num_fused_shared_experts > 0 and "mlp.shared_expert." in name:
# 将共享专家权重重命名到对应的融合槽位,否则会被跳过
name = name.replace("mlp.shared_expert.", f"mlp.experts.{num_experts}.")
# ...
评论区精华
风险与影响
- 风险:
- 影响范围受限:改动仅在
_use_aiter 为真时生效,即 AMD 平台且设置 SGLANG_USE_AITER,其他平台无影响。
- 潜在的未覆盖场景:PR 明确说明不支持融合检查点变体(单个
experts.gate_up_proj 张量),若未来出现此类检查点,可能导致加载失败。
- 测试覆盖缺失:本 PR 未添加自动化测试,且 CI 中可能没有覆盖相关场景,存在回归风险。
- 影响:
- 用户影响:修复了 AMD 平台上 Qwen3.5 MTP 推理吞吐量下降的问题,恢复至预期性能。
- 系统影响:仅影响 MTP 草稿模型的加载逻辑,不影响正常模型推理。
- 团队影响:改动较小,降低了维护成本,但需注意未来对融合检查点的支持。
- 风险标记:缺少测试覆盖, 特定平台相关
关联脉络
- PR #33889 Make shared-experts-fusion per-runner: 该 PR 引入了按 runner 的共享专家融合开关,导致 MTP 草稿模型开始融合共享专家,是本 PR 需要修复的根因。
参与讨论