MoE 推理中的 Expert Parallel、KV Cache 与大规模专家并行架构解析
核心结论: KV Cache 解决的是历史 token 的 Attention 重算问题;Expert Parallel(EP)解决的是 MoE 专家参数的跨设备放置问题。Decode 时,历史 token 不会重新经过 MLP/MoE,但每个新位置的 hidden state 仍必须逐层完成 Attention 与 MLP/MoE 计算。
1. 从 Transformer MLP 到 MoE
一个典型的 Transformer Block 可以抽象为:
flowchart TD
A["Hidden State"] --> B["Self-Attention"]
B --> C["Residual + Normalization"]
C --> D["Dense MLP 或 MoE"]
D --> E["Residual + Normalization"]
传统 Dense MLP 通常包含上投影、非线性激活和下投影:
在 SwiGLU 等结构中还会增加门控投影。每个 Transformer Layer 通常拥有各自独立的 Attention 和 MLP 参数,因此第 10 层与第 11 层的 MLP 一般不共享权重。
需要避免一种过度简化:不能机械地把浅层称为“只负责低层语义”、深层称为“只负责推理”。不同层确实会形成不同表征,但功能通常是分布式、渐进式形成的。
2. MoE 如何替换 Dense MLP
MoE(Mixture of Experts)通常把部分或全部 Transformer 层中的单个 Dense MLP,替换为 Router 加多个 Expert MLP:
flowchart TD
X["Token Hidden States"] --> R["Router / Gate"]
R --> E1["Expert 1"]
R --> E2["Expert 2"]
R --> EN["Expert N"]
E1 --> C["Weighted Combine"]
E2 --> C
EN --> C
每个 Expert 本质上是一个独立的 FFN,拥有自己的参数。对 token 的 hidden state
其中
Expert 的输入不是 token ID,而是当前 MoE 层接收到的 hidden state。其输入、输出维度通常都等于模型 hidden size;Expert 内部会先扩展到 FFN intermediate size,再投影回 hidden size。
3. 每一层都有自己的 Expert 吗?
对采用 MoE 的层,通常是:每个 MoE Layer 都有自己的一组 Router 和 Expert 参数,不同层之间一般不共享。
但并非所有 Transformer 层都必须是 MoE 层。常见变体包括:
- 每隔若干层放置一个 MoE Layer;
- 同时存在 routed experts 与 shared experts;
- Expert 在单层内独立,但不同层采用不同数量或不同结构;
- 少数研究架构会探索跨层共享,但不是默认假设。
因此,“模型有 256 个专家”必须结合具体架构理解:它通常表示每个 MoE 层拥有 256 个 routed experts,而不是全模型从头到尾只共享 256 个 Expert。
4. KV Cache 保存什么,不保存什么
KV Cache 保存每一层 Attention 为历史位置产生的 Key 和 Value:
当处理下一个位置时,当前 Query 可以直接与缓存的历史 K/V 做 Attention,无需重新计算所有历史 token 的 Attention 投影。
KV Cache 不保存“历史 token 的 MLP 输出”供后续 token 查询,因为标准 Transformer 的 MLP 是逐 token 独立计算:当前 token 的 MLP 不需要读取历史 token 的 MLP 结果。历史 token 在上一轮已经完整通过所有层,其作用已经通过各层的 K/V 表示进入缓存。
| 对象 | KV Cache 是否保存 | Decode 时是否重新计算历史位置 |
|---|---|---|
| 历史 Key / Value | 保存 | 不重新计算,直接读取 |
| 历史 Query | 通常不保存 | 不需要 |
| 历史 MLP / Expert 输出 | 不作为 KV Cache 保存 | 不重新计算 |
| 当前新位置的 Attention 与 MLP/MoE | 尚不存在 | 必须计算 |
5. Decode 阶段到底计算哪个 token?
严格地说,如果当前已有 token 1 到 token 99,并把 token 99 作为本轮新增输入位置,那么模型会为这个位置逐层计算 hidden state,并最终得到预测 token 100 的 logits。采样出 token 100 后,下一轮再把 token 100 送入模型,用来预测 token 101。
工程讨论中常把“处理 token 100”和“生成 token 100”混用,所以容易出现编号差一位。真正不变的原则是:
- 每轮只对当前新增位置执行完整的逐层前向计算;
- 历史位置不再经过 Attention、MLP 或 MoE;
- 当前位置在每一层都要执行 Attention,并执行该层的 Dense MLP 或 MoE;
- 当前层新产生的 K/V 会追加到该层 KV Cache 中。
Prefill 阶段不同:Prompt 中的全部 token 会并行经过完整模型,同时建立 KV Cache。Decode 阶段才通常表现为“每个请求每轮一个新 token”。
6. 为什么 MoE 需要 Expert Parallel
MoE 的总参数量很大,但每个 token 只激活少数 Expert。Expert Parallelism 的核心是:把同一 MoE 层的不同 Expert 分散放置到不同设备上。
例如某一层有 256 个 Expert、使用 8 个 EP rank,则可以让每个 rank 放置 32 个 Expert。Router 决定每个 token 应发往哪些 Expert 所在的设备。
要注意,Expert ID 只在所属 MoE 层内有意义。一个 EP rank 通常会保存多个 MoE 层中分配给自己的本地 Expert,还可能保存或分片 Attention、Embedding、Shared Expert 等其他参数,并不是一张卡只保存全模型中的一个孤立 MLP。
7. 为什么 EP 产生 All-to-All 通信
假设各个设备先各自持有一批 token hidden states。Router 可能把这些 token 分配给分布在任意设备上的 Expert,因此一次 MoE 层通常包含两次重分布:
flowchart TD
A["各 Rank 的 Token Hidden States"] --> B["Router + Token Packing"]
B --> C["All-to-All Dispatch"]
C --> D["各 Rank 上的本地 Expert GEMM"]
D --> E["All-to-All Combine"]
E --> F["恢复 Token 原顺序并加权聚合"]
第一次通信把 hidden states 发送到 Expert 所在 rank;Expert 计算完成后,第二次通信把输出送回原 token 所在 rank,再按 Router 权重聚合并恢复顺序。
“EP 必然调用标准 All-to-All 集合通信”也不是绝对的。实现可以使用 All-to-All、All-to-All-v、点对点传输、融合通信 Kernel 或面向拓扑的自定义调度,但其逻辑本质仍是多源到多目的的 token dispatch 与返回。
8. 为什么不采用逐 Token 的远程 RPC
“远程调用 Expert”从逻辑上并没有错,EP 本身也确实是在远端设备上执行 Expert。区别在于执行粒度与调度方式。
逐 token RPC 会产生大量小消息、启动开销和同步等待,Expert 每次只收到很少的 token,难以形成高效率的大矩阵乘。高性能 EP 通常采用:
- Router 先为一批 token 生成目标 Expert;
- 按目标 Expert 对 token hidden states 进行计数、排序和打包;
- 批量跨设备 Dispatch;
- 每个 Expert 对收集到的一组 token 执行 grouped GEMM;
- 批量返回并恢复 token 顺序。
所以它仍可以被理解为“远程执行”,只是实现上采用批量数据搬运和异步流水,而不是细粒度请求—应答式 RPC。
9. 大 EP 与“一卡一专家”
所谓“大 EP”通常指 EP degree 很大,专家在大量设备之间细粒度铺开。在极端映射中,对某一个 MoE 层而言,每个 EP rank 可能只承载一个 routed expert,形成近似“一 rank 一专家”的布局。
这不意味着整张卡在整个模型生命周期中只保存一个 Expert。模型有多层 MoE,每张卡通常会在每个相关层保存一个或少数本地 Expert,并参与层间的 Attention、归一化、通信及其他计算。实际系统还可能采用 Tensor Parallel、Pipeline Parallel、Data Parallel 与 EP 的组合。
优势
- 将巨大的 Expert 参数容量分摊到更多设备;
- 降低单设备专家权重的显存压力;
- Expert 到 rank 的映射清晰,便于拓扑感知调度;
- 当批量足够大、路由较均匀时,可以形成高吞吐 grouped GEMM;
- 便于对热点 Expert 做复制或冗余部署。
代价
- EP 规模越大,跨设备 token dispatch 的通信域越大;
- Decode 每个请求每轮只有一个 token,若总并发不足,每个 Expert 收到的 token 太少,GEMM 效率下降;
- Router 可能产生热点 Expert,导致部分设备拥塞、其他设备空闲;
- 需要 capacity control、auxiliary load-balancing loss、expert replication、冗余路由或动态调度;
- EP 跨越超节点后,网络带宽、时延与拓扑差异会更加明显;
- 通信、计算、Permutation 与反向 Permutation 需要精细重叠。
10. 大 EP 为什么依赖超节点
MoE 推理性能不再只由单卡峰值算力决定,还取决于一个完整的数据通路:
超节点提供高带宽、低时延、全局或分层交换能力,使更大 EP 通信域成为可能。但网络硬件本身并不足够,还需要软件栈协同:
- 拓扑感知的 Expert 放置;
- 高性能 token dispatch/combine Kernel;
- 通信与 Expert 计算重叠;
- 动态负载均衡和热点 Expert 复制;
- Continuous Batching 与请求调度;
- EP、TP、PP、DP 的联合并行策略;
- Prefill/Decode 分离场景下的流量规划。
NVIDIA 体系通常围绕 GPU、NVLink/NVSwitch、集合通信与推理软件栈协同优化;昇腾体系则围绕 Ascend NPU、片间/节点内高速互联、HCCL、CANN、MindIE 等组件协同。二者面对的共同问题都是:怎样以最低的数据搬运和同步代价,让动态路由的 token 高效找到对应 Expert。
11. 性能分析时应关注的指标
| 维度 | 关键指标 | 典型问题 |
|---|---|---|
| 计算 | Expert GEMM 利用率、每 Expert token 数 | 小 batch 导致矩阵过瘦 |
| 通信 | Dispatch/Combine 带宽与时延 | 跨节点 All-to-All 成为瓶颈 |
| 路由 | Expert 负载方差、丢弃率、热点程度 | 部分设备排队,部分设备空闲 |
| 内存 | Expert 权重、KV Cache、通信缓冲区 | 容量竞争或频繁换入换出 |
| 服务 | TTFT、TPOT、吞吐、尾延迟 | 吞吐优化损害单请求延迟 |
12. 总结
- 每个 Transformer 层通常拥有独立 MLP;采用 MoE 的层通常拥有独立的 Router 与 Expert 集合。
- Expert 的输入是当前层的 token hidden state,输出通常仍为 hidden-size 向量。
- KV Cache 缓存的是各层历史位置的 K/V,不缓存 MLP 结果。
- Decode 时只有当前新增位置逐层执行 Attention 与 MLP/MoE,历史 token 不重新计算。
- EP 的核心是跨设备放置 Expert,并根据 Router 结果搬运 token hidden states。
- EP 通常经历 Dispatch 与 Combine 两次多对多通信;Expert 本身不需要彼此直接“对话”。
- 高性能实现不是逐 token RPC,而是批量打包、通信、grouped GEMM 与流水重叠。
- “一卡一专家”应理解为某个 MoE 层在高 EP degree 下的一种细粒度映射,而不是整张卡只保存全模型中的一个 MLP。
- 大规模 MoE 的竞争焦点是计算、互联、路由、调度与软件 Kernel 的系统协同。
知识关联: 本主题连接 Transformer MLP、Sparse MoE、KV Cache、Continuous Batching、Grouped GEMM、集合通信、超节点互联,以及 EP/TP/PP/DP 混合并行。