当前位置:首页 > 中国芯 > 端侧AI
[导读]导读: MoE 搬到端侧,卖点一直写在算力上:0.3B 激活对 1.3B 总参数,FLOPs 少 2 到 4 倍。同一组数字换个方向看就变了味。INT4 下常驻内存从 450 MB 涨到 650 MB,每 token 的访存从 450 MB 降到 150 MB,出字速度只快 2.2 到 3.4 倍。省下的是算力,卡住的是容量。

MoE 搬到端侧,卖点一直写在算力上:0.3B 激活对 1.3B 总参数,FLOPs 少 2 到 4 倍。同一组数字换个方向看就变了味。INT4 下常驻内存从 450 MB 涨到 650 MB,每 token 的访存从 450 MB 降到 150 MB,出字速度只快 2.2 到 3.4 倍。省下的是算力,卡住的是容量。

两成激活是怎么来的

稀疏专家模型把每层的全连接块切成若干份,每份叫一个专家,再放一个小路由器给每个 token 打分,只让得分最高的几个专家参与计算。Mixtral 8x7B 的做法是每层八个专家、每个 token 选两个,总参数 47B,激活参数 13B,比例 28%。

端侧的做法把规模压下来。MobileMoE 这一族模型的激活参数在 0.3B 到 0.9B 之间,总参数 1.3B 到 5.3B,激活比例 17% 到 23%。这个区间是有意选的:激活参数决定算力,总参数决定容量,端侧两头都紧,只能在中间找位置。

路由本身也要花钱。每个 token 过一次路由器,要算 N 个专家的得分,再排序取前 k 个。N 等于 8、k 等于 2 时,这部分计算量相对专家内部的两层矩阵乘可以忽略,但它带来的访存不能忽略。被选中的专家权重不在片上,得从内存里搬进来,而且每个 token 选的专家可能不同,搬运的地址每次都在变。

算力与内存分开记

两笔账要分开写。算力按激活参数算,C = 2 × Pact × Ntoken,系数 2 是一次乘加。内存按总参数算,M = Ptotal × b / 8,b 是每个权重的比特数。两条式子里的参数不是同一个数,这是 MoE 全部反直觉的来源。

把数字代进去。0.3B 激活、1.3B 总参数、INT4 量化,b 取 4,每个参数半个字节。常驻内存 650 MB,每 token 参与计算的权重 150 MB。作为对比,一个 0.9B 的稠密模型 INT4 下是 450 MB,每 token 全部参与计算,访存也是 450 MB。

于是出现一组交叉:MoE 的每 token 访存是稠密的 1/3,常驻内存却是稠密的 1.44 倍。前者决定速度,后者决定装不装得下。端侧设备的两个约束恰好一个松一个紧,紧的那个被 MoE 放大了。

稠密模型的这两笔账是同一个数,优化方向因此很单一:压位宽、压参数量,两条其实是一条。MoE 把两笔账拆成两条线之后,优化方向也分岔了,一条降激活参数,一条降总参数,两者的收益不叠加。工程上最常见的错误是只盯第一条,把稀疏度一路推高,激活参数好看了,装机时发现内存不够。

图 1 稠密模型与两档 MoE 的三笔账(依据原文第 3 节绘制)

算术强度只有四

把速度差算清楚,要看机器的拐点。手机上的 LPDDR5X 带宽按 68 GB/s 算,NPU 的 INT8 算力按 30 TOPS 算,两者相除得到 441 FLOP/byte。这是这台机器的拐点:算术强度高于它,算力是瓶颈;低于它,带宽是瓶颈。

MoE 在 decode 阶段的算术强度是 2 FLOP 除以 0.5 字节,等于 4 FLOP/byte。与拐点差 110 倍。这个差距说明一件事:decode 阶段根本没有用到算力,每一个权重被搬进来只做两次运算就丢掉。

所以 FLOPs 少 2 到 4 倍,速度并不会照着这个比例涨。速度由访存决定,访存按激活参数降,理论上该快 3 倍,实测 2.2 到 3.4 倍,落在预期区间里。多出来的损耗来自路由查表、专家切换时的地址不连续,以及 KV 缓存那部分与专家数无关的固定开销。序列越长,固定开销占比越高,加速比越接近下限。

位宽这条路上还有一层。算术强度与每个权重的字节数成反比,INT4 是 4 FLOP/byte,降到 INT2 变成 8,离 441 的拐点仍然差两个数量级。低比特在端侧的价值不在算力,在于把权重压小、把每 token 的访存降下来,方向与 MoE 减少激活参数一致,两者可以叠加。

这也解释了为什么端侧 MoE 的报告里,prefill 的加速比(1.8 到 3.8 倍)和 decode 的加速比(2.2 到 3.4 倍)不一样。prefill 是矩阵乘为主,算力参与得多;decode 是逐 token 生成,带宽说话。同一套权重,两个阶段的瓶颈不同。

带宽的标称值还要打折。68 GB/s 是 LPDDR5X 的峰值,实际跑起来受刷新、温度、与 CPU 争抢影响,取到 50% 到 60% 是常态。按 40 GB/s 算,150 MB 的激活权重搬一遍要 3.75 ms,这就是单个 token 的时间下限。算力时间只有 0.02 ms,差了近两个数量级,算子写得再好也动不了这条线。

稀疏度不是越高越好

直觉上,稀疏度越高,激活参数越少,速度越快。端侧不成立。

把总参数从 1.3B 推到 5.3B,激活参数从 0.3B 推到 0.9B,稀疏度从 4.3 倍升到 5.9 倍。每 token 访存从 150 MB 涨到 450 MB,速度反而退回去;常驻内存从 650 MB 涨到 2.65 GB,8 GB 手机上系统只给应用 2.5 GB 左右,直接装不下。

稀疏度提高带来的收益是模型质量,代价是容量。端侧设备缺的恰恰是容量,不是算力。这就是 MobileMoE 那篇工作提到的甜点:中等稀疏度,配上细粒度专家和共享专家。共享专家每个 token 都要过,权重常驻、复用率高,能把访存的固定开销摊薄;细粒度专家把一个大专家拆成几个小的,同样的激活参数下组合更灵活,路由的粒度更细。

细粒度还有一层副作用。单个专家变小之后,一份权重有可能整块放进片上 SRAM,命中率上去,访存从外部内存变成片上。但专家数量一多,路由表、门控权重、索引都要占地方,在 0.3B 激活的模型里这部分能吃掉几个百分点的片上容量,而片上容量本来就是端侧最紧的资源。

量化在 MoE 上还有一点便利。每个专家的权重分布不同,缩放因子可以按专家单独算,一个专家里的离群通道不会污染另一个专家。稠密模型只能整层共用一个缩放因子,要么掉精度,要么加位宽。代价是缩放因子本身要存,每个专家一组,参数总量多出千分之一量级。

图 2 总参数规模与内存、出字速度的关系(依据原文第 4 节绘制)

端侧的上限在三 B

按 INT4 算,3B 总参数的 MoE 常驻 1.5 GB,加上 KV 缓存和运行时开销,落在 2 GB 上下,这是 8 GB 手机能接受的上限。再往上只有两条路,一条把位宽降到 3 比特甚至 2 比特,另一条把一部分专家放进闪存按需换入。后者在带宽上立刻吃亏:UFS 的顺序读在 2 GB/s 量级,比 LPDDR 低一个数量级,一次专家换入就是几十毫秒,而生成一个 token 的预算是几十毫秒。两条路都在拿精度或者速度换容量,没有一条不需要付账。

另一条路是把路由做在编译期。输入类型可预测的场景,比如固定的唤醒词加固定的几条指令,可以提前把可能用到的专家权重固定在片上,把动态路由变成静态子图。代价是通用性,换一个任务就得重新编译。

还有一种折中:按请求难度分流。简单请求只走共享专家加一两个小专家,复杂请求才展开完整路由,判断放在调度层而不是模型内部。常驻内存按总参数算,一点没少,但平均激活参数降下来,速度按请求分布加权。代价是调度层要先判断难度,这个判断要么靠规则,要么再挂一个小模型。

一句话:端侧 MoE 省的是算力,付的是容量,而这台设备最缺的正是容量。

内容来源:arXiv 预印本(开放获取)

原文标题:MobileMoE: Scaling On-Device Mixture of Experts

作者:Yanbei Chen, Hanxian Huang, Ernie Chang, Jacob Szwejbka, Digant Desai

DOI 或链接: https://arxiv.org/abs/2605.27358

配图说明:自行绘制,为原理示意,非原文原图复制

改动声明:对开放获取文献的技术编译与解读,标题、行文与配图为原创

来源:21ic电子网

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
关闭