一万亿参数的模型给编码 Agent 当大脑,每天要吞吐掉数千亿个 token。Modal 把这套推理服务调优完之后,单副本的每用户性能涨了 2.8 倍,副本整体吞吐涨了 5.6 倍。数字不稀奇,稀奇的是他们找瓶颈的顺序——先怀疑路由,再怀疑算子。
真正吃掉预算的,不是矩阵乘法
编码 Agent 的请求形状,跟聊天机器人差得远
一轮闲聊,几百个 token 进、几百个 token 出,上下文的生命周期短得可以忽略。编码 Agent 完全不是这个形状。它每次调用模型,前面挂的是整个代码库的检索片段、几十个工具的定义、之前每一轮工具调用的返回值和报错堆栈。模型真正新产出的 token 可能只有几百个,但要重新读进去的上下文动辄十万起步。
这就决定了一件事:长前缀复用才是这类负载的主战场。谁在长前缀上偷懒,谁就是在拿最贵的卡干最便宜的活。
同一个 token 被重算一次,账就翻一倍
Kimi K2.6 这类万亿参数的 MoE 模型有个特点:prefill 阶段吃算力,decode 阶段吃显存带宽,两者的资源画像完全不同。如果每一轮请求都把那段从没变过的前缀重新跑一遍 prefill,等于让本该安安静静做 decode 的卡,反复回去做一遍它昨天就做过的作业。
Modal 的处理方式很直接——把前缀缓存当成第一等公民。按 block 切分、按哈希索引,每一层的 KV 都存下来,命中就跳过计算。概念不新,难的是让这些缓存在正确的副本上、在正确的时间点还活着。缓存失效的时机、淘汰的粒度、副本扩缩容时缓存的迁移,才是真正耗掉工程时间的部分。
延迟和吞吐,在这里其实是同一场仗
常规做法里,想要吞吐就加大 batch,首 token 延迟认栽。编码 Agent 不吃这一套。开发者在屏幕前等着,工具调用是串行链路,一个会话卡住,后面几十步全部卡住。
所以吞吐优化必须顺带把延迟也做掉。而在长上下文负载里,这两件事被同一组瓶颈绑死了:显存带宽、KV 缓存容量、以及最容易被忽略的缓存命中率。你不可能通过牺牲一个来换取另一个。
把请求送到"记得它"的那台副本
路由的第一原则是前缀亲和
Modal 在负载均衡层做的事情,跟传统的轮询、最少连接数完全是两个思路。请求进来,先算它的前缀 block 哈希,再看哪个副本手里握着最多这些 block。命中率高的副本优先接单——哪怕它此刻看起来更忙。
算盘很简单:一次二十万 token 的 prefill,比任何程度的负载不均都要贵得多。把请求发给一个空闲但"失忆"的副本,等于用一份优雅的资源利用率,换来一次昂贵的重复计算。
缓存总量是一回事,有没有用上是另一回事
很多人盯着 KV 缓存能放多少 GB,这其实是个次要指标。真正决定成本的是命中率:进来的请求有多少比例、有多大比例的 token,真的落在了缓存里。
100GB 的缓存,配一套糟糕的路由策略,实际省下的算力可能还比不上 20GB 缓存配一套好路由。副本之间的命中率方差,往往比平均命中率更能说明问题——方差大,意味着有一批副本在反复做无用功。
会话粘性:同一个用户不该被轮着分配
编码 Agent 的上下文是长出来的,不是一次性灌进去的。第一轮也许只有三万 token,到第五十轮可能已经十五万,而且每一轮都在尾巴上继续加。
中途把会话甩到另一个副本,前面辛苦攒下的 KV 缓存全部作废。会话粘性因此变成硬需求。麻烦在于它不是一条简单的哈希规则:副本下线怎么办、超时怎么续、扩缩容时怎么迁移,每一个都是会真实发生的边界情况。
5.6 倍吞吐是从哪儿抠出来的
让 prefill 和 decode 分家
两种性质不同的活放在同一批 GPU 上跑,结果一定是互相拖累。一个正在进行的长 prefill 会把 decode 的批处理窗口挤碎,首 token 延迟的尾部分布立刻失控。分离部署是常见答案,但分离之后,KV 缓存要从 prefill 节点搬到 decode 节点,网络带宽就成了新的天花板。
所以分离不是终点,只是一道新的起点题:传输要能重叠在计算里,缓存要能分层落地,不然省下的干扰成本会原封不动地变成传输成本。
一万亿参数得摊开,还不能摊出一堵通信墙
Kimi K2.6 每一层都有数量庞大的专家,但一次前向只会激活其中一小撮。这意味着参数量可以摊到很多张卡上,代价是每次路由都要做 all-to-all 通信。
专家怎么分组、热点专家要不要多放几份、通信能不能和计算重叠着走——这几件事调不好,加卡不但不提速,反而更慢。万亿参数模型的并行策略,本质上是在通信和计算之间找那条最窄的缝。
显存账本要算到 KB 级别
权重占一块,激活值占一块,剩下全给 KV 缓存。注意力结构本身已经把 KV 压得相当紧凑了,但十万 token 量级的会话仍然是几十 GB 的体量。block 粒度切多大、碎片怎么回收、淘汰按什么顺序,这些细节直接决定了同一张卡能同时扛几个活跃会话。
承压能力上去了,副本数量才能下来,单位 token 的成本曲线才会真正弯下去。
换一支团队,这套方法能抄几成
先量分布,再谈优化
不要一上来就换框架、调并行度。先把 P50 和 P99 的首 token 延迟、每个请求的 prefill token 数、缓存命中率、以及副本之间的命中率方差拉出来看。Modal 的 2.8 倍和 5.6 倍,是这些指标先暴露出问题之后的产物,不是拍脑袋换来的。
数据的价值在于它排除了错误的努力方向。看到命中率方差高,你就不会去折腾算子了。
把"会话"当成调度单位
无状态路由在短上下文场景是美德,在长上下文负载里是负资产。当每个用户都拖着一条不断生长的上下文尾巴时,调度器最该关心的不是"哪台机器最闲",而是"哪台机器最懂这个用户"。
这个视角的切换,比任何单点优化都更值钱。
优化做完了,瓶颈会搬到隔壁
解决掉 prefill 对 decode 的干扰,瓶颈会挪到 KV 传输带宽上;缓存放对了位置,冷启动和扩缩容又变成新的短板;吞吐上去了,监控和成本归因的复杂度也跟着上去。
这类系统没有"优化完成"这个状态。所谓 2.8 倍和 5.6 倍,只是某一轮迭代结束时的快照——下一轮的故事,通常从今天最不起眼的那个指标开始。

