ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

万亿 MoE 只激活 4.9%:本机实测 7 种专家配置,细粒度比粗粒度慢 46%

万亿 MoE 只激活 4.9%:本机实测 7 种专家配置,细粒度比粗粒度慢 46% 万亿 MoE 只激活 4.9%本机实测 7 种专家配置细粒度比粗粒度慢 46%Mistral 在 10 月 6 日放出了 Mistral Large 4 的公开预览版1 万亿总参数、490 亿激活参数权重计划本月底开放。按官方口径算每个 token 只走 4.9% 的参数。我把一层同结构的稀疏前馈层搬到本机跑了一遍固定总参数量、扫了 7 种专家配置在激活比例完全相同的情况下把专家拆得更细并不会更快128 专家 top-8 比 32 专家 top-2 慢 46%。下面是我跑出来的数据以及这次实验的边界在哪。稀疏省的是算力不是显存MoE 一层的参数账很好算。设隐藏维度 d专家数 E每个专家的隐层宽度 d_ff一层前馈的参数是 3 × d × E × d_ff门控与上投影合并算两份下投影一份。只要 E × d_ff 不变总参数就不变每个 token 激活 top-k 个专家激活比例等于 k / E跟专家总数没有直接关系。Mistral Large 4 的公开数字是 1 万亿总参、490 亿激活比例 4.9%。同一份报道里还有两条信息值得记下来训练在欧洲自建数据中心完成用的是 3,800 块英伟达 Grace Blackwell GPU语料覆盖超过 160 种自然语言价格是每百万 token 输入 1.36 美元、输出 4.18 美元。这些数字来自 IT之家 10 月 6 日的报道权重还没放出来所以我没法在这台机器上真跑这个模型只能跑同结构的稀疏层。在本机搭一层细粒度 MoE本机没有装 torch整层用 numpy 写的。核心是路由加逐专家前向defforward(x,W1,W2,Wg,k):logitsx Wg.T# (T, E) 门控打分idxnp.argpartition(-logits,k-1,axis1)[:,:k]# 每个 token 选 top-k 专家outnp.zeros_like(x)foreinrange(Wg.shape[0]):rows,slotsnp.where(idxe)ifrows.size0:continuexex[rows]hxe W1[e]# (n, 2*d_ff)a,gh[:,:h.shape[1]//2],h[:,h.shape[1]//2:]ha*(1.0/(1.0np.exp(-g)))# 门控激活yh W2[e]# 回投到 dw1.0/(1.0np.exp(-logits[rows,e]))# 路由权重np.add.at(out,rows,(y.T*w).T)returnout实验设置d 固定 512E × d_ff 恒为 32768也就是每种配置的总参数都是 50.3M输入 512 个 token每种配置先热身一次、再跑 20 次取中位数。CONFIGS[(稠密,1,32768,1),(粗粒度,8,4096,1),(粗粒度 top-2,8,4096,2),(中粒度,32,1024,1),(中粒度 top-2,32,1024,2),(细粒度 top-4,64,512,4),(细粒度 top-8,128,256,8)]forname,E,d_ff,kinCONFIGS:# E * d_ff 恒为 32768总参数不变xnp.random.default_rng(42).standard_normal((512,D_MODEL),dtypenp.float32)W1,W2,Wgbuild(E,d_ff,np.random.default_rng(42))forward(x,W1,W2,Wg,k)# 热身ts[]for_inrange(20):t0time.perf_counter();forward(x,W1,W2,Wg,k)ts.append((time.perf_counter()-t0)*1000.0)print(name,E,d_ff,k,round(float(np.median(ts)),2),ms)跑完的真实输出稠密单专家 E 1 d_ff32768 k1 总参 50.3M 激活100.00% 中位1195.30ms 最快1014.21ms 相对稠密 1.00x 粗粒度 8 专家 E 8 d_ff 4096 k1 总参 50.3M 激活 12.50% 中位 117.49ms 最快 109.76ms 相对稠密10.17x 粗粒度 8 专家 top-2 E 8 d_ff 4096 k2 总参 50.3M 激活 25.00% 中位 235.78ms 最快 208.57ms 相对稠密 5.07x 中粒度 32 专家 E 32 d_ff 1024 k1 总参 50.3M 激活 3.12% 中位 65.45ms 最快 61.45ms 相对稠密18.26x 中粒度 32 专家 top-2 E 32 d_ff 1024 k2 总参 50.3M 激活 6.25% 中位 150.10ms 最快 111.87ms 相对稠密 7.96x 细粒度 64 专家 top-4 E 64 d_ff 512 k4 总参 50.3M 激活 6.25% 中位 160.41ms 最快 128.77ms 相对稠密 7.45x 细粒度 128 专家 top-8 E128 d_ff 256 k8 总参 50.3M 激活 6.25% 中位 219.62ms 最快 203.44ms 相对稠密 5.44x 细粒度 128 专家 top-8512 个 token 共 4096 次专家调用命中专家 128/128单专家最少 17 次、最多 46 次整理成表配置专家数 E每专家隐层 d_fftop-k激活参数占比512 token 前向中位耗时相对稠密稠密1327681100%1195.30 ms1.00×粗粒度84096112.50%117.49 ms10.17×粗粒度84096225.00%235.78 ms5.07×中粒度32102413.12%65.45 ms18.26×中粒度32102426.25%150.10 ms7.96×细粒度6451246.25%160.41 ms7.45×细粒度12825686.25%219.62 ms5.44×口径总参数统一 50.3ME × d_ff 32768d 512耗时是 20 次的中位数单位毫秒环境是 2 核 i5-1340P 的 WSL、Python 3.14.7、numpy 2.4.3数据全部为本机实测。三条从数据里能直接读出来的结论专家数与激活比例是两个独立旋钮。E8 配 top-1、E32 配 top-1、E32 配 top-2三者的激活比例分别是 12.5%、3.12%、6.25%而耗时 117 ms、65 ms、150 ms——决定算力的是 k / E不是专家数本身。同激活比例下粗粒度更快。32 专家 top-2、64 专家 top-4、128 专家 top-8 的激活比例都是 6.25%耗时依次是 150 ms、160 ms、220 ms。128 专家那档比 32 专家那档慢 46%。粒度细了每次矩阵乘的尺寸变小逐专家循环和结果归并的次数却翻了几倍。小批量下专家分散得很厉害。512 个 token 在 128 专家里做 top-8总共 4096 次专家调用128 个专家全部被唤醒单个专家最少的只拿到 17 个 token。这些几十行的矩阵乘在 CPU 上跑不出效率是延迟上不去的主要原因。我怎么用它先说这次实测的边界免得结论被放大。我这层是纯 Python 循环逐专家算、用np.add.at归并结果的朴素写法真实推理框架里这部分由分组矩阵乘和融合 kernel 承担专家拆细带来的调度开销会被摊薄不少。所以「细粒度更慢」这个结论只在单机 CPU 朴素养法下成立GPU 上未必我没有条件验证就不替它下结论。真正能复用的经验有两条。k 的影响基本是线性的E32 从 top-1 到 top-2耗时 65 ms 涨到 150 ms而专家数从 8 涨到 128、k 不动的话激活比例反而掉到 1% 以下得靠加大 k 补回来。显存账和算力账要分开算E × d_ff 不变时权重占用一模一样MoE 只在算力上省指望它省显存是想错了方向。坑也说一个第一次前向比后续慢不少稠密那档首次 1195 ms、最快 1014 msnumpy 的首次调用有额外开销取数我用的中位数而不是平均值用小样本跑基准的时候这点很容易把结论带偏。可以照着做的三件事选配置先算激活比例 k / E再倒推专家数。想做 5% 左右的稀疏E32 配 top-2 就够了不必上到 128 专家。单机或者 CPU 推理优先少而大的专家专家数上百的配置留给有分组矩阵乘的 GPU 服务。上线前在自己的真实批量上量一次专家命中分布。512 个 token 就能把 128 个专家全部唤醒命中过于分散时就该减专家数、加宽度。
返回列表