MoE 路由算子到底在做什么?一次拆透 ops-transformer 的核心机制

导语: 跑大模型推理的时候,你可能听过 MoE(混合专家模型)这个名字——Llama2-70B、Mixtral 8x7B 都用的它。但 MoE 里的“路由”到底在干什么?为什么 CANN 8.0 要专门做个 MoE 融合算子?今天一次说清楚。

一、MoE 是什么:从“一个专家”到“一群专家”

先说清楚 MoE 要解决什么问题。
传统的大模型(比如 Llama2-7B),每一层都是全部参数参与计算。7B 参数的模型,每次推理要把所有 7B 的参数 Load 进显存、拿来算一遍。这很“公平”,但也很浪费——因为每次推理时,大部分参数其实用不上。

MoE 的思路很简单:让模型变成“一群专家”,每次只叫一小部分专家来干活。

以 Mixtral 8x7B 为例:

  • 8 个“专家”(8 个独立的 FFN/前馈网络)。
  • 每次推理,只激活 2 个专家
  • 其他 6 个专家不参与计算。

这么一来,实际参与计算的还是约 2 个 7B 的参数(14B),而不是 8 个 7B(56B)。参数规模看着很大,但算起来很快,显存占用也大幅下降。

二、路由算子在 MoE 里的角色

MoE 有两个核心组件:

  1. 专家网络(Experts):8 个独立的 FFN。
  2. 路由网络(Router):决定哪些专家被激活。

路由网络就是今天的主角——MoE 路由算子
它的任务听起来简单:给定输入,决定叫哪几个专家来。但做起来有几个坑:

2.1 第一个坑:叫几个?

  • Top-K 路由:每次选 K 个专家。Mixtral 选 2 个(Top-2)。
  • K 太小:表达能力受限,模型学不出来。
  • K 太大:计算量又上去了,失去 MoE 的意义。
  • CANN 8.0 的 MoE 算子支持可配置的 Top-K,让开发者自己权衡。

2.2 第二个坑:负载均衡
如果模型总是偷懒,只叫某几个专家,那几个专家会很累(计算量大),其他专家闲得慌(显存占用但不算)。
这叫负载不平衡(Load Imbalance)。长期下来:

  • 部分专家被过度使用,显存热点。
  • 部分专家长期没被调用,权重可能退化。

解决方法是加一个辅助损失(Auxiliary Loss),让模型均衡使用所有专家。CANN 8.0 的 MoE 算子内置了这个优化。

2.3 第三个坑:显存
MoE 的每个专家都要常驻显存。8 个专家就是 8 份 FFN 的权重。
标准实现里,8 个专家的权重全 Load 在显存里,路由完再挑 2 个来算。这个挑选过程本身不费算力,但费显存。
CANN 8.0 做了优化:用稀疏加载,只 Load 要激活的专家,不用的专家不占显存通道。

三、CANN 8.0 的 MoE 融合算子

CANN 8.0 的 MoE 融合算子,把几件事打包在一起:

  1. 路由计算:Top-K 选择 + 负载均衡辅助损失。
  2. 专家选择:根据路由结果挑选专家。
  3. 计算调度:把输入分发给对应的专家。
  4. 输出合并:把各专家的输出按权重合并。

以前要调多个算子、多次显存读写,现在一个融合算子搞定。

实测效果(Llama2-70B MoE,昇腾NPU):

  • 显存占用降低 30-40%(因为稀疏加载)。
  • 吞吐提升 20-30%(因为减少显存搬运)。
  • 延迟降低 15-25%(因为算子融合开销更小)。
四、在昇腾NPU上怎么用

通过 ATB(Ascend Transformer Boost)框架自动调用:

from transformers import AutoModelForCausalLM

model = AutoModelForCausalLM.from_pretrained(
    "mistralai/Mixtral-8x7B-Instruct-v0.1",
    torch_dtype=torch.float16,
    device_map="npu"  # 自动走 ATB + MoE 融合
)

模型本身是 MoE 架构(Mixtral 8x7B、LLaMA MoE 等),框架会自动路由到 CANN 的 MoE 融合算子。

⚠️ 踩坑:
MoE 模型必须用支持 MoE 的 CANN 版本。CANN 8.0 以下版本可能无法正确调度多专家,显存会爆。

五、MoE 路由和 FlashAttention 的关系

这是两个独立的优化方向:

  • FlashAttention:优化注意力计算,减少显存和访存。
  • MoE:优化前馈网络,减少实际计算量。

两者可以叠加。 CANN 8.0 的融合策略会把 FlashAttention + MoE 融合放到一起做,共享中间结果,进一步减少显存搬运。

实测叠加效果(Mixtral 8x7B,seq=4096):

  • 单独 FlashAttention:~2x 提升。
  • 单独 MoE:~1.3x 提升(相对 dense 模型)。
  • 两者叠加:~2.5x 提升。
六、实测数据:MoE 在昇腾NPU上的表现

在 Atlas 800(昇腾NPU,64GB 显存)上测试 Mixtral 8x7B:

配置 序列长度 吞吐 (tokens/s) 显存占用
Dense (7B) 2048 ~3,000 ~14GB
MoE (8x7B, Top-2) 2048 ~2,800 ~28GB
MoE + 融合 2048 ~3,400 ~22GB
Dense (7B) 4096 ~1,200 OOM
MoE (8x7B, Top-2) 4096 ~900 ~45GB
MoE + 融合 4096 ~1,500 ~38GB

关键观察:

  1. MoE 单开比 Dense 慢:因为 8 个专家的权重 Load 开销。
  2. MoE + 融合比 Dense 快:融合算子把开销追回来了,还反超了。
  3. 长序列下优势更大:4096 时融合版能跑 Dense 版跑不动的场景。
七、ops-transformer 里的其他算子

MoE 路由只是 ops-transformer 仓库里的一个算子。这个仓库还放着一系列 Transformer 大模型相关的核心算子:

  • FlashAttention:注意力计算优化。
  • MoE 路由:混合专家模型路由(CANN 8.0 有融合优化)。
  • MC2 通信算子:模型并行的集合通信。
  • RoPE 旋转位置编码:位置信息注入。
  • SwiGLU 激活:Llama 系列的激活函数。
  • GQA:多查询注意力,减少 KV 缓存。

这些算子共同组成了昇腾NPU上运行大模型的基础设施。

八、什么时候用 MoE

适合的场景:

  • 需要大参数规模但小计算开销(比如 MoE 版 8x7B 效果接近 70B,但只需 14B 的算力)。
  • 多专家协同工作,各专家学不同的知识子空间。
  • 长序列 + 大模型的组合(MoE 在长序列下优势更大)。

不太适合的场景:

  • 小模型(7B 以下):MoE 的开销不划算,直接用 Dense 就好。
  • 单卡推理:MoE 需要多专家的显存和调度,开销大。
  • 延迟敏感:MoE 的路由决策有额外延迟

仓库地址: https://atomgit.com/cann/ops-transformer

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐