科技行者 2026-11-04 15:52:05
你有没有想过,一个大模型在回答你问题的时候,脑子里其实只有一小部分神经元在真正干活?
这就是混合专家模型的工作方式。
MoE*:Mixture-of-Experts,混合专家模型,指模型内部有一个很大的专家池,但每次处理一个词的时候,只会激活其中很少的几个专家来参与计算,其余的专家都在休息。
听起来很美好对不对?理论上这种稀疏性应该能省下大量的计算和内存开销。但2026年这篇来自a2sys和KAIST团队的论文,把这个美好的幻觉戳破了。问题出在一个几乎所有人都没意识到的地方:批处理。
**当很多个用户同时在用同一个模型回话的时候,稀疏性这个优点会悄悄消失。**
这事儿说起来有点反直觉。你可能觉得既然每个词只激活8个专家,那一批几十上百个请求同时跑,顶多也就激活这些专家对应的组合而已,怎么会用到全部专家?但论文里的公式和实测数据给出了答案:当批次里的请求数量上升到64甚至128的时候,几乎所有专家都会被触发,因为不同的词选择的专家组合五花八门,凑在一起几乎覆盖了整个专家池。
这就像一个大型自助餐厅,厨房里有256道菜的备料,每个顾客点餐只点8道。你可能觉得同时服务很多顾客也就顶多用到几十道菜的食材。但现实是,当顾客多到一定数量,几乎每道菜都会被点到,厨房不得不把全部256道菜的食材都准备好,哪怕每道菜其实只卖出去了几份。如果不提前全部备好,某个顾客想点的那道菜食材没备,响应就会卡住。这正是论文揭示的核心矛盾:专家池的稀疏性保证了计算量小,但保证不了内存搬运量小。
推理两阶段,脾气完全不同
要理解这篇论文的核心贡献,得先弄清楚大模型生成回答时经历的两个阶段。
Prefill*:预填充阶段,模型把你输入的整段提示词一次性处理完,为后续生成做准备。
Decode*:解码阶段,模型一个字一个字往外蹦,每生成一个新词就要做一次完整的计算。
这两个阶段的脾气完全不一样。预填充阶段因为要同时处理很多个词,专家的权重可以被反复复用,计算是瓶颈,内存搬运不是问题。但解码阶段每次只蹦出一个新词,每个专家可能就处理几个token,权重加载的开销根本摊不平,这时候瓶颈就变成了从显存里搬运专家权重的速度。
论文里有组数据特别扎心:在Qwen3.6-35B-A3B这个模型上,批次大小到64的时候,每一步解码要加载大约75%的专家池权重,等批次再大一点,几乎是整个专家池都要搬一遍。而专家一共60GB,这意味着解码阶段每一步都在被海量的权重搬运拖慢。
传统的解决思路是砍掉一部分专家,叫专家剪枝。
剪枝*:Pruning,通过某种重要性打分,把不常用或者贡献小的专家直接删除,只保留一部分专家池。
但这里出现了一个大家此前都没太在意的问题:**传统剪枝是把预填充和解码这两个脾气完全不同的阶段,用同一套被砍过的专家池来跑。**
这就好比一个餐厅为了省成本,把菜单从256道砍到128道,然后不管是堂食点餐高峰期还是打包外卖的低峰期,都用这套缩水菜单。堂食高峰期本来就是厨房在高速运转,顾客又多,砍掉一半菜品省下来的备料成本其实微不足道,因为大批量备菜本身效率就高。真正该省成本的,其实是打包外卖的那段时间,顾客零零散散来,每来一个都要重新准备一次菜,这时候菜单越精简,效率提升才越明显。如果不分场景,一刀切地砍菜单,堂食高峰期的顾客会明显吃到更差的菜,但省下来的成本却远远够不上这个代价。
论文用实测数据印证了这个直觉:把专家池砍掉四分之一到四分之三,预填充阶段的吞吐量几乎没有任何提升,顶多在百分之几的范围内波动。而解码阶段的吞吐量却能提升到1.5倍左右。这组对比数据,直接把传统剪枝方案的尴尬处境摆在了台面上:你为了提升解码效率去剪枝,结果却让计算本来就很充分的预填充阶段也跟着掉准确率,完全是赔本买卖。
SlimWise的核心想法:两个阶段用两套专家池
研究者的思路其实很朴素:既然预填充阶段砍专家没好处,解码阶段砍专家才有好处,那干嘛要用同一套专家池?
**让预填充阶段用完整的专家池,解码阶段用砍过的专家池,两边各管各的。**
这就是SlimWise的核心设计。听起来简单,但真正让这个想法能落地的,是一个技术细节:剪枝不会改变KV缓存的结构。
KV缓存*:KV Cache,模型在处理文本时为每个位置算出来的键值对,后续生成新词时可以直接复用这些缓存,不用重新计算。
因为剪枝只是去掉了一部分专家,不改变注意力模块和缓存的格式,所以完整模型跑完预填充生成的KV缓存,剪枝后的模型解码阶段可以直接拿来用,完全不需要做任何转换。
这就好比接力赛跑,第一棒跑完直接把接力棒交给第二棒,哪怕第二棒的运动员是临时换上来的一个轻装上阵的选手,只要接力棒的形状没变,交接就完全没有障碍。如果两个阶段之间需要做复杂的格式转换才能衔接,那这套方案基本没有实用价值,因为转换本身就要花费额外的时间和计算,抵消掉剪枝带来的好处。
论文里管这套机制叫KV缓存交接。
实验结果相当有说服力。在Qwen3.6-35B-A3B上砍掉一半专家,用三种不同的剪枝打分标准(路由权重总和、专家激活范数、还有综合两者的REAP方法)分别测试,发现只要让预填充阶段用完整模型,解码阶段用剪枝模型,准确率相比传统的两阶段都剪枝的方案有明显的回升,在好几个最受影响的测试场景里,差距被大幅缩小了。
而且这个效果是训练免费的,不需要额外调参,光是调整哪个阶段用哪套专家池,就能把准确率的损失捞回来一大块。
准确率没掉,但答案可能变了样
这里论文提出了一个让人意外的发现:光看准确率分数,是会骗人的。
研究者发现,有些剪枝后的模型,准确率看起来跟没剪枝差不多,但生成答案的长度却发生了巨大的变化。有的任务上答案突然变得特别短,短到让人怀疑模型是不是偷懒了,但恰好蒙对了答案;有的任务上答案却变得特别长,长到几乎把生成长度的预算都耗尽,模型还没说完。
比如在代码生成任务HumanEval+上,传统剪枝把回答的中位数长度从2300个token硬生生砍到300个token,但准确率只是略微下降。这就很可疑,一个正常写代码的过程应该包括分析问题、写代码、检查逻辑,这么短的回答意味着模型大概率跳过了大部分思考步骤,蒙对了答案而已。
反过来在数学题MATH-500上,中位数长度从2400个token涨到6600个token,90分位数也跟着大涨,但准确率竟然还维持在接近原来的水平。这说明模型在瞎绕圈子,说了很多废话但最后蒙对了答案。
这就像一个学生考试,表面上两次考试分数都是90分,但你翻开草稿纸才发现,一次是三下五除二迅速做完的,另一次写满了十几页纸反复涂改才憋出答案。两次分数相同,但学生对知识的掌握程度完全不一样,后一种情况下换一道稍微难一点的题目,学生大概率就露馅了。如果只看最终的分数而不去翻草稿纸,你永远发现不了这个问题。
**这也是这篇论文很有价值的一点:它提醒我们评估一个模型压缩方案好不好,不能只盯着基准测试分数,还得看模型的生成行为有没有被扭曲。**
论文还验证了这不是采样引入的随机噪声导致的假象,用确定性的贪婪解码重新测了一遍,发现这种长度扭曲依然存在,甚至更明显。说明问题出在剪枝后的解码器本身,而不是采样过程的偶然性。
蒸馏来救场:低成本微调方案
既然光靠KV缓存交接还不能完全解决生成长度扭曲的问题,研究者又加了一道工序:蒸馏。
蒸馏*:Distillation,让一个小模型或者被压缩过的模型去学习一个更大更完整的模型的输出分布,从而继承大模型的能力。
但这里的蒸馏方式跟一般做法不太一样。常规蒸馏是让学生模型从头到尾自己生成所有的缓存状态,但SlimWise部署时的真实场景是,学生模型(也就是剪枝后的解码器)要接手老师模型(完整模型)生成的前缀缓存,然后在这个基础上继续往下写。
所以研究者的训练方式刻意模拟了这个场景:对每条训练数据,随机选一个切分点,前半段让完整模型来处理生成缓存,后半段交给剪枝模型在这个缓存基础上继续预测,训练的损失函数也只计算后半段。
这就好比培养一个代班老师,你不会只让他在空教室里自己对着黑板练习讲课,而是直接把他扔进一个正在上课的班级,让他接着前一位老师刚讲到一半的内容往下讲。只有这样训练出来的代班老师,真正顶替上场的那一刻才不会手忙脚乱。如果只让他在空教室里从头备课,他可能讲得很流畅,但一旦要接别人的课,那种衔接的生疏感立刻就会暴露出来。
为了让这套蒸馏的训练成本足够低,研究者还做了个聪明的设计:只训练一小部分参数,把路由器、归一化层和共享专家这些"常驻岗位"的组件拿出来调,专家权重和注意力参数完全冻结不动。
在Qwen3.6-35B-A3B上,这部分可训练参数只占整个模型的0.42%,训练数据量也只用了大约1亿个token,整个训练过程在四块B200 GPU上大概六个小时就能跑完。
这跟动辄要用几十亿token重新训练一个剪枝模型的做法相比,成本低了好几个数量级。
更巧妙的是共享专家的扩容设计:研究者冻结原本的共享专家,又新加了一个同样宽度的专家,但这个新专家的输出投影层初始化为零。这意味着刚开始训练的时候,这个新专家完全不影响模型输出,之后慢慢学出一个额外的修正量。这种"先什么都不做,再慢慢纠偏"的思路,跟LoRA和ControlNet里用的零初始化技巧是一脉相承的。
加了蒸馏之后效果立竿见影。在砍掉75%专家这种极端情况下,原本的训练免费方案在MATH-500上的90分位数长度会直接撑到生成预算上限32768个token,蒸馏之后降到14000个token,虽然还是比完整模型的6100个token要长,但已经改善了一大截,同时准确率也从0.867提升到0.959。
落地到真实的推理系统
光有方法论上的突破还不够,这篇论文还把SlimWise真的塞进了实际的推理框架vLLM里,验证在两种常见的部署模式下都能用。
PD分离*:Prefill-Decode Disaggregation,把预填充和解码这两个阶段放在不同的硬件实例上分别处理,再把KV缓存通过网络传输过去,这样可以避免两个阶段互相抢占算力导致延迟不稳定。
在PD分离的场景下,解码实例可以直接加载一个只包含被保留专家的瘦身版模型文件,这意味着被砍掉的那部分专家原本占用的显存,全都能腾出来留给KV缓存,从而支持更大的批次。这是SlimWise相比其他一些"运行时动态选专家"方案的独特优势,那些方案虽然也能减少每步访问的专家数量,但完整的专家权重还是得全部放在显存里,省不出这块空间。
另一种部署模式是PD同位,预填充和解码在同一个实例上处理,这种情况下没法通过换模型文件来省显存,但研究者想出了另一个办法:路由掩码。
路由掩码*:直接在路由器的打分结果上,把要剪掉的那些专家的分数强行改成一个很小的负数,这样在选择最终激活的专家时,它们自然不会被选中,效果等同于真的把这些专家从模型里拿掉了。
这个办法妙就妙在不需要真的准备两份模型权重,预填充阶段用原始的路由器打分,解码阶段套上这层掩码,一份模型文件就能同时服务两种策略。
实测数据显示,在PD分离模式下,砍掉一半专家之后,解码吞吐量能达到完整模型的1.4到1.81倍,砍掉75%专家甚至能到1.65到2.39倍,而且对延迟要求越严格的场景,相对收益反而越大。PD同位模式下的提升稍微低一点,因为路由掩码本身会带来大约0.5毫秒的额外开销,占每步解码时间的2.5%到5%左右,但依然能拿到1.36到2.28倍的提升。
两个阶段谁更重要,答案因任务而异
论文里还做了一组特别有意思的对照实验,把预填充和解码两个阶段的剪枝状态做了全排列:都用完整模型、都用剪枝模型、预填充剪枝但解码用完整模型(叫Reverse配置)、还有SlimWise自己的预填充完整解码剪枝。
结果发现,不同任务对这两个阶段的敏感程度完全不一样。
在代码生成任务上,预填充阶段的完整性特别重要。Reverse配置(预填充剪枝、解码完整)在HumanEval+上的准确率只有0.890,跟SlimWise的0.929比明显差一截。但在数学题上情况反过来了,Reverse配置在GSM8K和MATH-500上的表现反而比SlimWise更好,说明数学推理这种任务,解码阶段如果专家被砍,更容易把整个推理链条带偏。
这就像修一栋房子,地基没打好,后面盖楼再怎么精心装修也白搭;但如果地基很扎实,中途偷工减料一下装修材料,房子照样能住,只是看起来没那么精致。代码生成更依赖"地基",也就是对提示词的完整理解;而数学推理更依赖"施工过程"中每一步的严谨程度,一旦解码阶段的专家被砍,推理链条很容易走歪,表现为生成长度异常膨胀,模型在那儿绕圈子找不到出路。
正因为任务敏感度不一样,研究者才坚持聚焦在给解码阶段做蒸馏,而不是反过来去蒸馏预填充阶段。因为蒸馏预填充没法解决真正的性能瓶颈,预填充本来就不缺计算资源,瓶颈从来都在解码这一侧的权重搬运上。
Q&A
Q1:SlimWise是什么?
A:SlimWise是一个让混合专家模型推理更高效的服务框架,核心做法是让预填充阶段用完整专家池、解码阶段用剪枝后的专家池,两个阶段通过同一套KV缓存直接衔接,不需要额外转换。
Q2:SlimWise能带来多大的速度提升?
A:在Qwen3.6-35B-A3B模型上,砍掉一半专家后,解码吞吐量在PD分离部署下能提升到完整模型的1.4到1.81倍,砍掉75%专家甚至能到2.39倍,且准确率损失很小。
Q3:为什么传统的专家剪枝方法效果不好?
A:因为传统方法会把预填充和解码两个阶段用同一套被砍过的专家池处理,但预填充本身是计算密集型,砍专家几乎没有提速效果,却白白牺牲了模型准确率,属于赔本买卖。
【版权声明】本文内容来源于科技行者,版权归原作者及原媒体所有。本站仅作信息分享,不构成任何商业用途;如涉版权问题,请联系本站删除。
发布时间:2026-11-04 13:04:17
(第1/1页/共6470字/8阅)