DAC'26 | ExpertFlow 让 MoE 推理不再被显存卡脖子:单卡跑 Mixtral-8x7B,吞吐最高提升 10 倍

DAC’26 | ExpertFlow 让 MoE 推理不再被显存卡脖子:单卡跑 Mixtral-8x7B,吞吐最高提升 10 倍

原文:ExpertFlow: Efficient Mixture-of-Experts Inference via Predictive Expert Caching and Token Scheduling

代码:github.com/expertflow-dac/expertflow | 权重:huggingface.co/expertflow-dac/models


1. 前言

先交代下背景:我们团队的 ExpertFlow 被 DAC 2026 录用了,而且大会这两天(7 月 26–29 日)正在 Long Beach 进行中,所以趁热和大家聊聊这篇工作到底解决了什么真问题。代码和训好的 predictor 权重都已经开源(链接见文章开头),欢迎大家来踩。

这篇工作的出发点其实很朴素:MoE 模型号称”稀疏激活”,但显存占用一点都不稀疏。以 Mixtral-8×7B 为例,跑一次推理需要 96 GB 以上的 GPU 显存,一张 80 GB 的 A100 都塞不下。但离谱的是,它 46.7B 参数里有 45.1B 属于 expert 模块,每个 token 实际只激活其中 2/8 的 expert——也就是说,90% 以上的参数在大部分时间里全程闲着,却要全程占着显存

“计算稀疏、内存稠密”,这就是 MoE 落地绕不过去的核心矛盾。最直接的思路是 offloading:把不用的 expert 放在 CPU 内存,需要时再搬进 GPU。想法很自然,但真做起来会结结实实踩三个坑,这也正是 ExpertFlow 要解决的三个问题。

2. MoE offloading 的三个坑

坑一:expert 预测不准、不及时。 offloading 要想不拖慢推理,就必须提前知道”接下来哪些 expert 会被用到”,才能提前把它们搬上 GPU。已有方法分两派:回归派直接拟合 router 打分,但打分的微小误差就会改变路由结果,往往需要大量 fine-tune 来补救;分类派里的启发式方法(基于 token-expert 统计)轻量但抓不住输入相关的路由行为,学习式方法(如 ProMoE)精度上去了,却是逐层预测——要等上一层跑完才知道下一层的 expert,调度空间被压得很死。

坑二:expert 利用率低。 decoding 阶段 batch 通常不大,token 在 expert 之间的分布可能极度不均,最坏情况是每个 expert 只分到 1 个 token。而 expert kernel 处理少量 token 时开销几乎是常数,这种碎片化的分配等于让 GPU 空转。

坑三:缓存策略失效。 GPU 上的 expert cache 常用 LRU 策略,但 LRU 只看”最近用过谁”,完全无视 MoE 动态路由的模式,命中率很不稳定。SE-MoE 用 ring-buffer 缓存相邻两层的所有 expert,locality 是好了,但对 Switch-128 这种一层 128 个 expert 的模型,内存开销直接爆炸,还会反复搬运根本不会被激活的 expert。

3. ExpertFlow:预测驱动的三件套

我们的解法是把整个推理过程重构成一条”先预测、再调度、后执行”的流水线,三个组件互相咬合。

ExpertFlow 系统总览

如上图,给定两个输入 batch:① Routing Path Predictor(RPP)一次性预测所有 token 在所有层的 expert 激活;② Token Scheduler(TS)根据预测结果跨 batch 重组 token,把路由路径相似的 token 聚到一起;③ Expert Cache Engine(ECE)只把需要的 expert 从 CPU 预取进 GPU;④ 模型带着优化后的 token 流和 CPU/GPU 异构的 expert 放置开始执行。

3.1 Routing Path Predictor:一次前向,预测全部层

RPP 结构示意

RPP 用的是 T5 风格的 encoder-decoder:encoder 编码完整输入序列,decoder 上挂 L 个轻量预测头,每个头输出对应 MoE 层的 E 个 expert 的激活概率,最终得到形状为 (B, S, L, E) 的概率矩阵。训练时把每个 token 的路由路径编码成 {0,1} 的二值矩阵,当成 multi-label 分类任务用 binary cross-entropy 学。

和逐层预测的方案比,关键区别在于:第一个 MoE 层还没开始算,整条路由计划就已经出来了,prefetching 和内存规划可以从推理一开始就全局展开。而且这个 predictor 非常小——网格搜索后的最终配置只有 7.21 MB,相对于动辄几十 GB 的 MoE 本体几乎可以忽略。

3.2 Token Scheduler:把”人以群分”用在 token 上

Token Scheduler 重组 token 示意

如上图左侧的最坏情况:4 个 expert、两个 batch 各 4 个 token,每个 batch 都把所有 expert 激活了一遍,但每个 expert 只算 1 个 token——搬运成本拉满,计算效率拉胯。TS 拿到 RPP 的预测后,把两个相邻 batch 的 token 合并再重新划分,让路由路径相似的 token 进同一个 batch。重组后(右侧)每个 batch 只激活一半 expert,每个 expert 一次算 2 个 token。

严格求解这个划分问题是 intractable 的,所以我们用 K-means 风格的聚类做近似:以路由路径的 Hamming 距离构造相似度矩阵,迭代地把 token 分成两个等大的簇。整个过程跑在 CPU 上,开销 <10ms。重组会打乱 KV cache 的顺序,所以 TS 还配了两个轻量原语:Merge 按全局 token 顺序重建 KV cache,Reindex 更新 token 索引,保证 attention 语义不变。

3.3 Expert Cache Engine:预测性缓存 + 运行时纠错

Expert Cache Engine 工作流

ECE 包含两部分。PLEC(Predictive Locality-aware Expert Caching)不像 LRU 那样按”最近使用”被动淘汰,而是按预测的 expert 需求主动分配 cache slot:哪层预测要用的 expert 多,就多给几个坑位,然后提前把最可能激活的 expert 搬上 GPU。Real-time Correction 负责兜底——预测不可能 100% 准,一旦发现预取错了(比如上图里多搬了 e23、漏了 e24),就在其他 expert 计算的同时用高优先级队列做 swap,把 I/O 藏进计算里。

另外,RPP 和 TS 本身也有开销,为此我们设计了 Dual-Batch Pipeline:把两个 batch 绑成一个调度单元,当前单元在 GPU 上做 prefill/decode 时,下一个单元的 RPP 预测和 TS 重组在旁路并行执行,互相不阻塞。

Sequential vs Dual-Batch 流水线对比

4. 实验:数字说话

实验在单张 A40(48 GB)上做,覆盖 6 个 MoE 模型(Switch-32/64/128、Mixtral-8×7B、Qwen1.5-MoE、Deepseek-MoE)和 4 个数据集(Alpaca、WMT16、XSUM、AIME2024)。

各 MoE 模型配置

4.1 吞吐

不同模型和数据集上的吞吐对比

如上图,在 Switch 系列上,expert 数越多、显存越紧,收益越大:(CS=16, BS=32) 时对 SE-MoE 的加速比从 Switch-32 的 2.01× 涨到 Switch-128 的 5.86×;在 Switch-128 上进一步把 cache size 压到 4,加速比拉到 9.99×。对 Mixtral-8、Qwen1.5、Deepseek-MoE,相对最强 baseline Cache-MoE 的提升分别最高 1.99×、2.12×、1.94×。

这里说句实在话:10× 这个数字出现在 expert 数量极多、cache 极小的 Switch-128 场景,属于我们方法的”主场”;在 Mixtral 这类 expert 少而大的模型上,收益是 2× 左右——依然可观,但不是处处 10×,大家看数字的时候可以留意下配置。

4.2 跨域泛化

一个自然的质疑是:predictor 是在特定数据集上训的,换个任务是不是就废了?我们用 Alpaca 上训的 RPP 直接去跑 WMT16 和 XSUM:

跨域 predictor 的吞吐表现

加速比依然稳定在 1.78×–2.21×,说明 RPP 学到的 expert 激活模式有相当的任务无关性。预测精度上,in-domain 场景大多 90% 以上,cross-domain 一般掉 5–10 个点。

各层 expert 预测精度对比

如上图,对比两个启发式 baseline——TLP(拿上一个 decoding step 的路由当预测)和 SLP(拿上一层的路由当预测)——RPP 全场领先,在 Switch-64 上 baseline 精度不足 20% 时 RPP 还能维持 80–90%。

4.3 显存

GPU 显存占用对比

对比把全部参数放 GPU 的 All-in-GPU(AIG):Switch-128 从 15.26 GB 降到 1.03 GB(约 93% 的削减),Deepseek-MoE 从 31.35 GB 降到 6.38 GB,Qwen1.5 从 35.21 GB 降到 6.52 GB。最有意思的是 Mixtral-8×7B:AIG 直接 OOM,我们的系统 15.99 GB 就能跑完——这意味着一张消费级的 24 GB 卡理论上也能伺候得动。

4.4 消融

cache 策略上,PLEC 对 LRU 的命中率优势在 batch 变大时越拉越开:CS=8、BS=16 时 PLEC 命中率 71.89%,LRU 只有 36.22%;CS=16 时 PLEC 最高到 91.96%。

PLEC 与 LRU 缓存命中率对比

TS 的贡献单独拆出来看:Switch-32/64/128 上分别带来 1.03×、1.15×、1.17× 的吞吐提升。趋势也符合直觉——expert 越多,token 分配越碎,重组 batch 的收益就越大

Token Scheduler 消融结果

5. 一些冷静的讨论

自夸完了,也聊聊边界,免得大家以为这是银弹:

  1. RPP 需要为每个模型单独训练。虽然只有 7.21 MB、训练数据靠跑 10000 条输入自动收集,成本不高,但换模型就得重训,做不到即插即用。
  2. 收益和 expert 粒度强相关。expert 多而小的模型(Switch 系列)收益最大;expert 少而大的模型(Mixtral)单个 expert 的搬运延迟更难藏,收益就收敛到 2× 附近。
  3. 目前实验集中在单卡 offloading 场景。不过路由预测这个信号本身是通用的,往分布式 expert placement、routing-guided pruning、多级缓存上延伸都是很自然的方向,我们也在往这边推进。

总结一下,ExpertFlow 的核心思想一句话就能说清:与其被动应对 MoE 的动态路由,不如先把路由预测出来,让调度和缓存都”未卜先知”。预测(RPP)、调度(TS)、缓存(ECE)三件套环环相扣,最终换来最高 93.72% 的显存削减和 10× 的吞吐提升。

论文正在 DAC’26 现场展示(7 月 26–29 日,Long Beach),在场的朋友欢迎来交流。代码和权重都在:

有问题欢迎评论区交流,也欢迎直接在 GitHub 提 issue。


顺带扯句题外话:ExpertFlow 里”用一个小模型去预测大模型的行为,再据此做系统优化”的思路,和 AutoML 里”用 proxy 评估架构好坏”其实是一脉相承的——都是用便宜的预测换昂贵的执行。我们把这些年在 AutoML/NAS 和 LLM 效率优化上的积累整理成了一本书《动手学 AutoML:从 NAS 到大语言模型优化实战》,里面有 LLM 压缩(剪枝/量化)、模型融合的章节,和本文的推理加速角度不同,但目标一致:让大模型跑得更省。感兴趣的朋友可以翻翻。

动手学AutoML书籍封面

Flag Counter