用户点下按钮,界面转了一会儿才出结果。产品同事问是不是模型太大,工程同事先看日志,发现请求在队列里等了一阵。这样的场景里,推理优化往往不是一句“换个小模型”能解决的,它更像一次把等待拆开的工作:哪一段在算,哪一段在等,哪一段本可以不发生。
先分清慢在请求的哪一段
同一个响应时间,可能来自输入预处理、分词、排队、批处理等待、模型前向计算,也可能来自结果返回前的后处理。把它们混在一起谈,容易把系统问题误判成模型问题。一个实用的起点,是给请求链路加上足够细的时间切片:进入网关是什么时候,拿到执行槽是什么时候,首字输出是什么时候,完整结束又是什么时候。
这些切片不需要一开始就很完整,但必须能回答一个问题:等待主要发生在计算之前,还是计算之中。如果大量时间耗在排队,单看算子耗时就会偏离现场;如果首字延迟和完成延迟差距明显,交互方式和解码策略就值得单独拿出来看。
缓存和批处理改变的是等待的形状
缓存常被当作推理优化的快捷方式,但缓存命中率背后是请求分布和内容复用程度。把不该缓存的结果缓存起来,短期看似省了计算,长期却可能带来一致性问题。批处理也一样,它把多个请求的等待重新排列,可能提升资源利用率,却不自动让每个用户都更快。对交互式场景,批处理窗口开多大,要和可接受的首字延迟一起考虑;对离线任务,关注点则可能转向吞吐和任务完成时间。
- 先确认业务真正在意的是首字延迟、完成延迟,还是单位时间处理量。
- 再看缓存键是否稳定,失效策略是否清晰,避免把一致性成本藏到后面。
- 批处理参数不要只按资源占用调,还要观察等待时间的分布,而不是只看平均值。
监控与回退是推理优化的一部分
很多推理优化讨论集中在模型结构和算子,但线上系统里,监控与回退常常更早暴露问题。没有按版本、按请求类型拆开的延迟视图,就很难判断一次改动影响的是哪类流量。回退机制也不是悲观设计,它让团队在尝试新批处理策略或缓存策略时,有一个可恢复的边界。把灰度、限流、降级和日志采样放在同一张图上,推理优化才不至于变成一次无法复盘的调参。
我更愿意把这件事看成工程判断:先承认等待有多个来源,再用可观测性把问题缩小,最后在延迟、吞吐和实现复杂度之间做取舍。模型当然重要,但在很多响应慢半拍的现场,真正需要改的可能是请求入口、排队策略,或者一次不必要的重复计算。