vLLM-07|MegaMoE 与 FusedMoE:路由相同,算 expert 完全不同

02 篇把 --moe-backend deep_gemm_mega_moe--enable-expert-parallel 标成 Flash eval 的硬约束;06 篇讲完 KV 怎么占显存。本文想要分享的是:MoE 一层 forward 里,谁负责选 expert、谁负责算 expert,以及 MegaMoE 与 FusedMoE 在分片轴上的差别。跨卡 all2all、DeepEP 在 15 篇;权重 finalize_mega_moe_weights 在 14 篇。以下以 vLLM main 的 models/deepseek_v4/nvidia/model.py 为准。

一层 MoE forward 概览

DeepSeek-V4 的 MoE 不是「每个 token 过一遍全部 routed expert」。checkpoint 里 n_routed_experts 是路由表大小(具体数字看 config.json),num_experts_per_tok 才是每个 token 实际激活的 k;forward 只算这 k 路,其余 expert 权重不参与本次矩阵乘。

每个 decoder layer 里,FFN 前的 RMSNorm 已在 hyper-connection 融合 kernel 里与残差流一并处理(09 篇),再进入 DeepseekV4MoE。Flash eval 快路径上,一层 MoE 可收成下面这条链:

bash 复制代码
hidden_states(已 ffn_norm)
  → GateLinear              # hidden → fp32 router_logits
  → fused_topk_bias         # sqrtsoftplus 选 expert;Hash 层另查 tid2eid
  → prepare_megamoe_inputs  # EP symmetric buffer 上 pack hidden + topk
  → fp8_fp4_mega_moe        # DeepGEMM MegaMoE kernel
  → (+ shared_experts)      # 若有 n_shared_experts
  → reshape 回 token 维

Gate 对每个 token 的 hidden 打出 router logits;fused_topk_bias 根据 scoring 函数和(可选)Hash 查表,得到 top-k 个 expert 编号与权重;MegaMoE 再在 EP 组的 symmetric buffer 上 pack 输入,调用 DeepGEMM fp8_fp4_mega_moe 只算被选中的 expert。若 checkpoint 配置了 n_shared_experts,shared MLP 对全部 token 全量计算,结果加回 routed 输出。

--moe-backend 换成非 deep_gemm_mega_moe 的值,同一层会走 FusedMoE:路由仍可用同一套 GateLinearfused_topk_bias(Hash 表经 hash_indices_table 传入),expert 计算改走 vLLM 通用 fused kernel,并按 tensor parallel 切 expert,而不是 EP。

MegaMoE 与 FusedMoE:同一份权重,两条分片轴

开关在 VllmConfig.kernel_config.moe_backend(CLI --moe-backend):

ini 复制代码
self.use_mega_moe = (
    vllm_config.kernel_config.moe_backend == "deep_gemm_mega_moe"
)
路径 experts 类 expert 权重怎么切
use_mega_moe == True DeepseekV4MegaMoEExperts EPget_ep_group(),每 rank 持一段 physical expert
use_mega_moe == False FusedMoE TPn_physical_experts // tp_size,按 tensor parallel rank 切

假设某 token 路由命中 expert #12#47。MegaMoE 路径上,每张 GPU 持若干 expert 的整份权重(按 EP 均分);若 #47 不在本卡,要把该 token 的 hidden 送到持 #47 的 rank,算完再加权汇总,矩阵乘走 DeepGEMM 的 fp8_fp4_mega_moe。FusedMoE 路径上,gate 仍打出同样的 #12#47,但 expert 权重按 TP rank 切分,每张卡只存自己那份分片,用 vLLM 通用 fused MoE 算子完成 forward。

同一份 Flash checkpoint,换 backend 换的是 expert 算子与分片轴,不是只换一个 kernel 名字。Attention 仍可按 --tensor-parallel-size 切 head(02 篇);MegaMoE 路径下 MoE expert 用 EP,不用 TP 切 expert。规划卡数时要同时满足:TP 能整除 head 数,EP 组大小能整除 physical expert 总数(见下节,以 HF config 为准)。

开 MegaMoE 时,约束分两阶段出现,排障时不要混为一谈:

条件 何时检查 不满足时
enable_expert_parallel == True DeepseekV4MoE.__init__ NotImplementedError
scoring_func == "sqrtsoftplus" init MegaMoE 仅支持该路由
expert_dtype == "fp4"(Flash 典型) init MegaMoE 仅支持 fp4 experts
CUDA SM100(capability major == 10) finalize_weights DeepGEMM MegaMoE requires SM100 GPUs
hidden_size / moe_intermediate_size 为 128 倍数 _check_runtime_supported(finalize 内) ValueError

因此 eval 能过 init、首 token 或首次 MoE forward 才报错,常见是 SM100 或 128 对齐在 finalize 阶段才触发。关掉 deep_gemm_mega_moe 会落到 FusedMoE + TP 分 expert------不是「Flash 绝对不能纯 TP」,而是官方 eval 快路径绑定了 MegaMoE + EP + fp4 + sqrtsoftplus + SM100 这一组组合。

deep_gemm.fp8_fp4_mega_moe 之前,prepare_megamoe_inputsnvidia/ops/prepare_megamoe.py)会在 EP group 的 symmetric buffer 上 pack 本 batch 的 hidden、scale 与 topk 索引/权重。这一步是在多卡 MoE 里把输入整理成 kernel 要的 layout,属于 EP 侧的输入 staging;token 如何派发到持有对应 expert 权重的 rank、all2all 走 DeepEP 还是别的 backend,由 parallel_config 决定。

路由:GateLinear、sqrtsoftplus、Hash 两层逻辑

Gate 是 GateLineargate_linear.py):对 hidden 做线性变换,输出 fp32 router logits。MegaMoE 路径在块外先 self.gate(hidden_states),再调 fused_topk_bias

sqrtsoftplus 与 correction bias

Flash checkpoint 常用 scoring_func == "sqrtsoftplus"。CUDA 路径走 ops.topk_hash_softplus_sqrtfused_topk_bias_router.py):先把 logits 变成 scores = sqrt(softplus(logits))。

非 Hash 层且在 topk_method == "noaux_tc" 时会挂 e_score_correction_bias(HF 权重名 .ffn.gate.bias 加载时映射到此字段)。选哪 k 个 expert 时,用 scores + bias 做 top-k;写进 topk_weights 的数值,是从未加 bias 的 scores 里,按选中 expert 做 gather 得到的。源码注释写明:bias 只参与 expert 选择,不参与权重计算。

Hash MoE:查表定 expert,gate 定权重

num_hash_layers 层是 Hash MoE(extract_layer_index(prefix) < config.num_hash_layers)。init 里挂 tid2eid,形状 [vocab_size, top_k],Hash 层不用 e_score_correction_bias

ini 复制代码
is_hash_moe = extract_layer_index(prefix) < config.num_hash_layers
if is_hash_moe:
    self.gate.tid2eid = nn.Parameter(...)  # [vocab_size, top_k]

Hash 层的路由分两步:

  1. Expert 编号 :由 input_idstid2eid[token_id],每个 token id 对应预定义的 k 个 expert id。
  2. Expert 权重:gate 仍要算;从 sqrt(softplus(logits)) 得到的 scores 里,按上一步查到的 expert id 做 gather,得到 topk_weights。

因此 forward 里若 tid2eid is not Noneinput_ids is None,会直接 ValueError------没有 token id 就无法查表。DeepseekV4Model.forward 在 MegaMoE 下会把 input_ids 转成 int64,每层 ffn(x, input_ids) 传入;prefill 与 decode 都需要这条链。排障「Hash 层路由全错」时,先确认 input_ids 是否传到 MoE,再查 gate logits。

EP:physical expert 怎么切到各张 GPU

Expert Parallel(EP)的含义是:不同 GPU 各持一部分 expert 权重;某个 token 激活的 expert 若不在本卡,需要跨卡通信把 token 送过去、再把结果收回来(通信细节在 15 篇)。--enable-expert-parallel 写入 parallel_config.enable_expert_parallel;MegaMoE 还要求此项为 True,否则 init 即失败。

MegaMoE 的 _init_mega_moe_experts 从 EP group 取 rank,按 physical expert 均分:

python 复制代码
self.ep_group = get_ep_group()
self.ep_size = self.ep_group.world_size
self.n_local_physical_experts = self.n_physical_experts // self.ep_size
self.experts_start_idx = self.ep_rank * self.n_local_physical_experts

n_physical_experts = n_routed_experts + n_redundant_experts(EPLB 的 redundant replica 算进 physical 总数),必须能被 ep_size 整除,否则 assert。本 GPU 只加载 experts_start_idx .. experts_end_idx 这一段权重;DeepseekV4MegaMoEExperts.weight_loader_map_global_expert_id 跳过不属于本 rank 的 global expert。

fused_topk_bias 输出的 topk_ids 先是 logical routed expert 编号。若开了 EPLB,MegaMoE forward 里还会经 eplb_map_to_physical_and_record 映射到 physical replica,再进 prepare_megamoe_inputs

启动失败与 forward 异常怎么收窄

栈若在 DeepseekV4MoE.__init__,可先对照:

CLI / checkpoint 代码触点
--moe-backend deep_gemm_mega_moe kernel_configuse_mega_moe
--enable-expert-parallel MegaMoE init assert
expert_dtype=fp4 + scoring_func=sqrtsoftplus HF config.json → 同上 assert

已通过 init、运行中数值或性能异常,可沿 router logits → topk_ids → Hash 层是否缺 input_ids → MegaMoE 是否已完成 finalize 往下查。

收尾

Flash eval 的 MoE 快路径是 MegaMoE + EP:路由侧 GateLinear 出 fp32 logits,再经 fused_topk_bias(sqrtsoftplus;早期 Hash 层用 tid2eid 定 expert id、gate 定权重,且必须传 input_ids);计算侧 prepare_megamoe_inputs 做 EP staging 后调 fp8_fp4_mega_moe。关掉 MegaMoE 则走 FusedMoE,expert 按 TP 切------路径存在,是否与 Flash checkpoint 匹配需自行 benchmark。

下一篇 08 ------ deepseek_v4_fp8 线性层量化与 MXFP4 experts(Flash 与 Flash-Base 在权重量化上的分水岭)。

相关推荐
JeJe同学1 小时前
Opencv之高斯金字塔
人工智能·opencv·计算机视觉
得物技术1 小时前
得物知识问答:复合检索 Agent 的系统设计实践
人工智能·后端·ai编程
机器学习之心1 小时前
基于改进鲸鱼优化算法的CNN-BiLSTM-MATT短期电力负荷预测模型
人工智能·算法·cnn·cnn-bilstm-matt·短期电力负荷预测
南方程序猴1 小时前
Codex 将再次重置:GPT-6.0 发布前的黑暗时刻
人工智能·gpt·ai·ai编程
一线数智1 小时前
从百度搜索到AI推荐 制造业正在迎来新的获客方式
人工智能
天天爱吃肉82181 小时前
【工程师笔记|新能源整车电控一次过CISPR25/BCI,汽车EMC/EMI落地十大核心设计技巧】
大数据·人工智能·笔记·python·汽车
9i编程1 小时前
SKILL 四大铁律准则:从「AI 选择性执行 SKILL」到「铁律强制闭环」
人工智能·openai·ai编程
windliang1 小时前
Claude Code 源码分析(十):MCP 外部工具如何进入下一轮 Agent 调用
前端·算法·面试
后端小肥肠2 小时前
自研长篇小说写作 Skills:参考文风 + 自动续篇 + 剧情连续性检测
人工智能·aigc·agent