← 返回系列总览
[从零训练一个500B大语言模型] 5/25:MoE怎样用一部分参数,完成一次计算?

[从零训练一个500B大语言模型] 5/25:MoE怎样用一部分参数,完成一次计算?

上一页的图还摊在桌上:蓝色A取回前文,金色B接着加工,一层层走到底,模型接出后面的文字。我沿着金色B又看了一遍。500B稠密模型里,每来一个token,各层这整套网络都要工作。容量继续做大,每次经过它的计算也跟着涨。

于是冒出一个问题:模型能不能装下更多学到的东西,每次却只动用需要的那一部分?文字各不相同,完整的B每次全部上场,似乎还有重新安排的空间。

我在B旁边多画了几套网络,入口加一道选择:当前token交给其中几个,其余的留给别的输入。这样改出来的就是MoE。总参数决定模型保存多大的容量;每次选多少专家,决定这个token调用多少计算。这两个数字终于可以分开安排。增加的容量能带来多少能力,还得交给训练与评估回答。眼前更迫切的问题是:这条少算一些的路,到了GPU上,真的会更快吗?

先沿同一个token走进B,看看它怎样选路。等这条路走通,再把专家搬到不同GPU上,时间究竟省在哪里就能逐项追了。

B每次全部计算,能不能换一种安排?

原来的B只有一套权重。“雨”来一次,“拿起”来一次,都由它加工。文字不同,输入向量不同,使用的仍是同一套网络。

新图把B展开成多套网络,每套都有自己的权重,接收一个向量,再输出一个向量。这便是“专家”。沿着方框往里看,仍能找到上一篇那些带权重的连接:输入的数字经过计算,变成新的数字。

同一层的蓝色A之后,将金色B从一个前馈网络换成路由器与多套专家;分格短条是向量,E方框是一整个网络

图上的A与B还在原来的位置。圈出B以后,下一张图就把这个位置打开。分格短条是一整个向量,小格是其中一个数;E1、E2方框则各是一整套专家网络,里面可能保存很多参数。

起名字时,很容易顺手写上“数学”“编程”“语文”。我先把这些名字擦掉,换成E1、E2。训练通常从相似结构与不同初始权重开始,分工会随着数据形成。它们可能偏向某些特征,也可能形成难以用学科名字概括的处理方式。保留编号,反而更容易看清实际发生的计算。

MoE(Mixture of Experts):在模型的一部分设置多个专家网络,每个token只选择其中一部分参与计算的结构。

专家:这里是一段有自己权重的前馈网络,接收和输出向量。

稠密模型:在本文的对比中,每个token都使用各层同一套完整的前馈网络。

谁来决定请哪几个专家?

句尾的“my”经过A,已经带着前文的信息。可四个专家都在等,输入究竟该交给谁?B的入口多了一小段网络,先读这个向量,为各个专家打分。这就是路由器。

我先让四个专家每次选两个,把一条路径画完整。此次选中了E1与E3,结果按75%与25%混合。E2、E4的权重仍保存在模型里,这个token这一次不调用。下一次输入变了,或走到另一层,选择也可以变。

选路并没有把输入切成两半。E1、E3各拿到同一个完整向量,分别加工。把两份输出写在纸上:E1是 [0.8, 0.2, -0.4],E3是 [0.4, 0.6, 0.8]。接着按路由比例逐格合并:

0.75 × [0.8, 0.2, -0.4] + 0.25 × [0.4, 0.6, 0.8] = [0.7, 0.3, -0.1]

第一格算成 0.75 × 0.8 + 0.25 × 0.4 = 0.7,其余两格照着算,最后仍是一条同样宽的向量。这份结果就是B的输出,可以继续沿着层里的连接往下走。

跟踪一个向量:路由器选E1和E3,两专家各处理完整输入,输出按75%和25%逐分量合并;E2和E4本次未选

图里最容易混淆的地方,也在这一步露出来:短条是一串数,专家方框是一段网络,75%只是一个数,用来乘输出向量的每个分量。箭头负责标出数据去向,专家内部的可学习连接留在方框里面。

把比例取成75%与25%,合并结果便很容易逐格核对。真正确定模型配置时,还要选定打分、Top-k、归一化的方法,有的设计也会加入缩放。眼前这条路已经能顺着走完:读状态,选专家,各自算,再合并。

A和B都在算比例,看上去相似,选的东西却各有位置。A决定从哪些文字位置取信息,B决定把当前位置交给哪些网络加工。前文先被取回来,再进入专家;两步接起来,模型的整条路没有断。

路由器(router):读取当前状态,为专家打分并决定选用哪些专家的小网络。

Top-k:从一组候选中选取分数最高的k个。图里k等于2。

路由权重:混合专家输出时使用的比例,由当前输入和路由方法确定。

每次都需要的工作,放在哪里?

专家池画出来以后,又遇到一件事:有些加工会被很多输入反复需要,每次都让路由器选择,未必是最合适的安排。于是给B留一条每个token都会经过的路径,叫共享专家;旁边那些按需选择的,叫路由专家。

输入来到B,一路进入共享专家,另一路送往选中的路由专家。两边各自产生向量,再按模型的组合方式汇合。调用范围不同,接收与加工向量这件事相同。

常用的加工有了固定去处,路由专家便有机会形成各自的处理方式。具体分工要从训练后的行为观察;共享与路由这两个名字,先把每个输入经过哪些路径说清楚。

把图复制到下一层时,还要换上下一层自己的专家和路由器。同一层的各个位置共用本层专家池,下一层有自己的权重。一个词沿网络走下去,状态改变,遇到的专家池也改变,选路自然可以不同。

这些选择最终都要经受同一件事的检验:后面的文字预测得怎么样。误差沿参与计算的路径返回,调整专家与路由器的可学习权重。输入一批批经过,谁负责什么、怎样选择,逐步在训练中形成。

共享专家:在采用这种设计的MoE层里,每个token都会调用的专家网络。

路由专家:由路由器为当前token选出的专家网络。

保存500B,为什么这次只用150B?

路径画通,参数账却有了两个数。我在表头分别写下“总参数”和“激活参数”:前一个数清模型保存多少可学习的数,后一个数清一个token这次调用多少。

先排一份圆整的500B结构账本。共同路径的主要矩阵计算取整记为100B,包括注意力投影、共享专家等;另400B放在各层的路由专家中。每层设置16个同样大小的路由专家,每次选2个。

这时路由部分就有了明确的算法。所有层保持同样的选择比例,400B里每次调用的主要矩阵参数为:

400B × 2 ÷ 16 = 50B

共同路径每次仍然要走,所以把100B加回来:

100B + 50B = 150B

500B参数账本:100B共同部分加400B路由部分,路由专家每层选2个共16个,每token约调用150B;色块面积表示参数量

图里的400B是各层路由专家的合计,十六格表示共同的调用比例;实际每层仍有自己的专家池。色块面积表示参数量,既不是向量,也不对应GPU张数。输入查表等细项,留到完整配置清单里逐项核对。

账本上仍然保存500B,单个token主要调用约150B。只看这些权重的主要乘加,150B约是500B的30%。省下的工作有了出处:未选中的专家,这次不用为这个token计算。

但训练用时那一栏还不能直接填30%。注意力、路由、数据搬运、参数更新都在继续,长上下文还会增加注意力开销。沿着整条路径把这些工作加回来,才能谈时间。

显存也没有跟着变成150B。没被这个token选中的专家仍要保存,下一批输入可能就会用上;同一批里许多token合起来,也可能覆盖许多甚至全部专家。训练还要保留相应参数状态。账本至此分成了两张:存多少,和每个token算多少。

总参数:模型保存的全部可学习参数数量。

激活参数:一个token沿当前计算路径调用的参数数量。比较模型时要核对它是否包含共享部分,以及统计的是哪一种运行路径。

显存:GPU用来存放模型、当前数据和计算中间结果的内存。

四个专家同时算,选两个会更快吗?

写下“少算”之后,我仍有一个疑问:GPU本来就能并行,少选两个专家,另外两张卡空着,怎么会省时间?先把问题缩到最直接的摆法:四个专家各占一张GPU,只有一个token,每个专家都需要1毫秒,输入已经送到。

调用方式同时工作的GPU闲置的GPU专家计算完成时间
四个专家全部计算4张0张1毫秒
只选择两个专家2张2张1毫秒

表里两行都是1毫秒。四个专家原本就能同时完成,选两个以后,留下的两个仍各算1毫秒。工作总量减了,当前token的等待时间没有减;另两张卡确实闲着,权重还占着显存。

这张表迫使我回头看GPU实际怎样计算。它的计算单元数量有限,一个大矩阵常常要拆块、分轮处理。参数保存在显存,计算单元反复读取和计算,并不是每个参数都有一颗专用计算单元。NVIDIA的矩阵乘法指南把这种分块安排讲得很具体。原来需要多轮才能做完的工作,减少以后,才有机会减少轮数。

于是时间也得分开问:一个token多久拿到结果,一整批token多久处理完。刚才那张表回答前一个问题。我们的训练一次有许多token,接下来得把整批任务摆到四张卡上,看看是否还会这样空着。

计算单元:GPU内部实际执行运算的部件,会反复处理不同的数据和参数。

延迟:一个请求从开始到得到结果所花的时间。上表只计算专家运算这一步的时间。

吞吐:单位时间完成的工作量,例如每秒处理多少token。

专家放到不同GPU,新的等待就出现了

摆到真实设备上,又多了一段路。专家分散在不同GPU,路由器选完,输入要送过去,输出还要送回来。纸上E1与E3之间短短的间隔,机器上可能要靠一次跨卡传输走完。

图里把E1放在GPU 1、E3放在GPU 2。一个输入向量发到两个地方,等两份输出都返回,才能合并。其他文字位置也各自带着路由结果,在这些设备间来回。

专家分到两张GPU:一个向量发送给选中的E1和E3,专家输出返回原位置合并;箭头是向量传输,卡片是GPU

再拉远一点。这个token去E1、E3,旁边的token可能去E2、E4。后两个专家没有接到前一个输入,却可以忙着加工后一个。一张GPU还可以保存多个专家,计算单元轮流接手它们的任务。

把一批100个token排进四张卡,每卡一个专家。如果每个token都调用四个专家,共400次调用,每卡100次;改成每个选两个,共200次,均匀分配就是每卡50次。原来要分多轮完成的工作,此时有机会提前结束。如果100次调用本来就能同时完成,减到50次依旧未必省时,还要看利用率和传输等待。这个计算先比较同一组专家的调用量,能力是否相当,要另做质量评估。

随后把路由结果往E1那边挪,新的问题马上出现:GPU 1前面排起队,其余卡可能没活干。批次太小也会出现类似空闲,少算的一部分成了闲置。想把节省的计算换成训练速度,还得让任务合理分布,同时保留按输入选专家的能力。

至此,MoE论文里反复出现的“负载均衡”和“通信”都有了具体位置。专家内部省的是计算,专家之间增加的是分发、传输与等待,两边一起决定整批数据何时完成。

我继续翻NVIDIA的Megatron Bridge性能指南,里面把专家分布、成组计算和通信放在一起处理:发往同一张卡的向量成批打包,传输尽量与计算同时进行,专家位置也配合设备连接安排。后面做B200并行训练与网络时,这些办法还会落到具体机器上。现在的检查表先加两项:每个专家收到多少任务,GPU又花了多少时间等待数据。

批次(batch):一起交给模型处理的一组训练数据,里面通常有很多token。

专家并行:把不同专家放到不同设备上,让输入按路由结果送过去计算。

通信:这里指GPU之间传输输入、输出等数据。

负载均衡:让工作合理分布到专家和设备上,减少一边排长队、一边闲置的情况。

公开模型里的384个专家,落在图上哪里?

带着这张图再看DeepSeek于2026年10月17日发布的V4.1-Flash-1017,一长串配置便有了落点。公开配置写着每个MoE层384个路由专家、每token选6个,另有1个共享专家。

把图里的四个专家扩成384个,把选两个改成选六个,再添上每次都走的共享路径,就是这个B的大致连接方式。专家各自仍是前馈网络,数据仍沿着“选出、发送、计算、合并”往下走。

这里的6/384只作用于路由专家。注意力与共享专家仍要计算,不能拿整个模型直接乘这个比例。刚才先从500B里划出100B共同部分,就是为了让账本能容纳这些固定经过的路径。

另一份公开设计给出了不同取舍。第四篇的Meta Muse Glimmer 30B保留稠密语言主干,面向本地运行;2026年10月15日发布的Muse Spark Open则用MoE,官方列出816B总参数、42B激活参数。同一个团队也会为容量、速度和部署条件选择不同路线。我们要借用的,是它们怎样做取舍,而后把自己的任务放回这张比较表。

再看DeepSeek报告里的552B、196B、8B和16B

技术报告把语言主干列为552B参数,另有196B的Engram记忆模块。Engram用另一种方式保存和取用信息,放到后面讲记忆时再展开。

报告中的8B和16B,分别对应读取输入与逐步生成的推理路径。它们说明这套架构怎样控制推理计算;从零训练时,要按训练实际经过的路径重新统计。计算本篇的MoE选择比例时,先找到路由专家那部分,再加共同路径,就能避免把全部主干都乘上6/384。

我们的500B项目,接下来怎样选?

回到项目表,仍然是500B稠密模型、10T累计训练token、5,120张B200,主训练排76天。这份工程基线继续往下走。旁边新增的500B、约150B激活账本,让MoE对照有了清楚的起点。

要把MoE真正列为替代方案,我会先补齐三栏:总共保存多少参数,每token调用多少,各层专家怎样放到设备上。圆整账本随后要展开成层数、向量宽度、专家大小和共享部分的完整清单。

接着让两条路线用相同数据与评估方法接受比较。同样计算投入,额外容量带来多少学习收益;到了多张卡,省下多少等待时间;各专家又是否得到了充分训练。目标规模的吞吐出来,训练周期、卡数和费用才能跟着重算。

绕过这圈,最初的问题也更准确了:多保存参数、少做每token计算,是MoE给出的机会;把机会换成时间,要靠整批任务和设备一起配合。沿路还有一件事始终没有打开:路由器、专家,连同前面的Attention,究竟怎样从文字里学会这些工作?下一篇回到一句“窗外下着雨,我拿起了伞”,顺着预测错误往回找,看它怎样改变网络里的数字。

新文章,直接发到你的邮箱。

AI、工程与实验,每月 1–2 封。

无垃圾邮件,随时取消。