问同一个问题,有时几秒就出答案,有时要盯着光标等上半分钟。用户感受到的是“今天有点卡”,工程侧看到的却是另一回事:模型规模没变,请求量没暴涨,变的只是这一次生成要走多少步、每一步要算多少。
这就是推理优化真正要处理的问题。它不神奇,也不只是把模型压小,而是在给定硬件和给定质量要求下,重新安排计算发生在哪里、发生多少次。
慢,未必是算得不够
大模型生成文本是一个逐字推进的过程。每吐出一个词,都要把已有的上下文重新过一遍网络。上下文越长,这一步越重;输出越长,重复的次数越多。于是同样一台机器,短问答显得轻快,长文档总结就会明显拖沓。
直觉上的解法是加卡。但在实际系统里,瓶颈常常不在算力峰值,而在显存带宽、批处理效率、请求排队方式这些更细的地方。一张卡空转着等数据,比算得慢更常见。推理优化要做的第一件事,往往不是换硬件,而是看清时间花在了哪。
省在哪里,决定了省得对不对
常见的做法大致落在几层:
- 缓存已经算过的中间结果,避免重复劳动,比如把长提示的公共部分留存下来复用;
- 降低单次计算的精度,用更省空间的数值格式换取吞吐;
- 把多个请求合并成批一起算,让硬件少有空等;
- 对输出长度做约束,或让简单问题走更短的路径。
这些手段单看都合理,叠在一起却会互相牵制。批合并能提高吞吐,但会让单个请求多等一会儿;降精度能省显存,但对数值敏感的任务可能带来细微偏差;缓存能加速重复前缀,却要额外占用本已紧张的空间。
所以推理优化的核心不是“哪个技巧更好”,而是先明确这一路请求更在意什么。面向实时对话,延迟优先;面向离线批量处理,单位成本优先。两类目标混在同一套配置里,通常两边都不讨好。
一个容易被忽略的边界
有些环节看起来很适合省,实际上不该动。比如需要严格依据长文本作答的任务,如果为了快而截断上下文,省下的是时间,丢掉的是准确性;再比如多步推理类请求,强行压缩中间步骤,表面响应快了,返工率反而上升。
更稳妥的判断方式是看“省下来的是冗余还是信息”。重复的前缀、可以合并的批、空转的等待,属于冗余,削减它们几乎无损;而上下文里的关键约束、答案的验证环节,属于信息,动了就会传导到结果质量上。
这也是推理优化常被误解的地方:它更像一次资源分配的重新谈判,而不是一次单纯的提速。谈判的对手不是硬件,是业务对速度和正确性的容忍度。
把它当成一件长期的事
模型会更新,请求结构会变,用户对等待的耐心也在变。今天调好的参数,几个月后可能又不再合适。因此比起追求一次到位的配置,更实际的做法是保留可观测的指标:每个请求的时间花在预填充还是逐字生成,批大小波动如何,缓存命中多少。有了这些,调整才有依据。
推理优化不是一个能一劳永逸解决的开关,而是一套持续校准的习惯。它要求团队既懂模型,也懂自己业务里哪些等待可以接受、哪些不能。想清楚这一点,省下来的才不只是账单上的数字。