卡加了,吞吐为何没跟上?大模型推理中的等待,有了新解法
大模型走向大规模在线服务,一个常见却又有些反直觉的现象是: 卡加得越来越多,吞吐却涨得越来越慢 问题出在哪?在 DeepSeek 等 MoE 模型的一类部署中,多组计算卡并行处理大量请求,每组既处理各自的请求,又要通过跨组通信,共同完成每一步解码。这意味着解码是齐步走: 只要最忙的一组没算完,其他组算得再快也只能等 更麻烦的是,请求即使分得一样多,各组实际承担的负载也可能不同,于是较轻的一组提前算完、空等最忙的一组,就成了常态。这种等待会随 token 生成反复发生,每一步都等一点,累积下来,部署规模扩大的收益便被悄悄吃掉了。 所以,瓶颈并不卡在算力那里,而是卡在「谁来等谁」上。 针对这一瓶颈, 香港科技大学周子杰团队与华为 2012 实验室理论部联合提出 BalanceRoute 。团队的思路很直接: 先把问题说清楚,再谈优化,即通过数学建模刻画同步等待,再将短期负载预测转化为在线路由决策。 效果也经得起检验。在论文的 96 卡主实验中,采用实际预测器的 BR-H 相对所比较的最强基线, 解码吞吐提升约 15% 这项工作已被 NeurIPS 2026 接收,并 已部署于双方共建的 MaaS 推理服务系统 MathBot-Pie 论文标题:Tackling the Data-Parallel Load Balancing Bottleneck in LLM Serving: Practical Online Routing at Scale 论文链接:https://arxiv.org/pdf/2605.06113 代码链接:https://github.com/b010001y/BalanceRoute 请求数相同,负载仍会不同 大模型生成回答,通常分为预填充(prefill)和解码(decode)两个阶段。预填充先处理整段输入,把后续生成需要复用的中间结果保存为 KV 缓存;解码再逐个生成输出 token。每生成一步,都需要读取此前输入和已生成内容对应的 KV 信息。 在本文研究的预填充 — 解码分离(PD 分离)系统中,这两个阶段由不同的计算资源承担。请求完成预填充后,路由器为它选择一个解码工作单元,已有的 KV 缓存也随之传送过去。一个单元可由多张计算卡组成。 轮询等方法可以依次把新请求分给各组,却没有区分每条请求需要处理多少 KV 信息。同样处理两个请求,长上下文对应的缓存更多,单步读取与计算的负担也可能更重。因此,在同步约束下,请求数相同,较轻的组等待较重的组仍是常见的问题。 图 1|预填充完成后,请求被分配到解码工作单元。下方展示本文部署中解码步内的计算与同步:每组都是两个请求,KV 总量却不同,较轻的组会等待最忙的一组。斜线为等待示意。 负载还会随生成不断变化。每生成一个 token,请求就会新增相应的 KV 信息,下一步需要处理的上下文也随之变长,请求完成,则退出后续解码计算。与此同时,预填充侧还在送来新请求。某组可能连续多步变忙,也可能因一条请求结束而突然减轻负担。 图 2|解码中的负载变化:新请求带着预填充得到的 KV 缓存加入,已有请求随生成增长,完成的请求退出。较轻的单元等待当前最忙的一组;同一请求始终留在原单元。 把运行中的请求转交给另一组,需要搬运已经积累的 KV 缓存。考虑这一开销,论文采用分配后不迁移的设定:路由器必须在输出长度未知、负载不断变化时作出选择,请求随后留在该单元直到结束。 数学建模,把同步等待变成决策目标 从每一步的同步关系出发,通过数学建模,把各单元与最重单元之间的负载差相加,得到不均衡指标。设第 k 步中,单元 g 负载为 L_g (k),最重单元负载为 M (k),一共有 G 个单元。单步不均衡可以写作: I (k) 这个量越大,说明各个单元之间的算力分配越不齐。这个指标刻画了同步等待对应的空闲,长期目标则是减少它在连续解码步骤中的累积。 如图 3,四组负载为 10、7、6、5,此时 I (k) 为 12。给 C 增加 4 单位负载,恰好填平它与最重单元的差距,I (k) 降至 8;若增加 5,C 就变成新的最重单元,让其他三组各多等一份,I (k) 为 11。 图 3|填补空闲与抬高峰值的权衡。两个接入方案均从同一初态出发;蓝色为已有负载,绿色为新增负载,斜线为空闲差额,粉色突出峰值上升带来的额外等待。数值为示意负载单位。 这个例子揭示了分配的关键权衡:接入新请求能填补较轻单元的空闲,但若把它推成新的最重单元,就会增加其他单元的等待。接下来,需要把这种比较延伸到未来多个步骤。 预测多远,取决于路由真正需要什么信息 一次分配的影响会延续到后续解码。两组此刻一样忙,其中一组若有请求即将结束,就可能很快释放负载。BalanceRoute 的 BR-H 因此引入 H 步窗口,估计