晚上十点,客服系统里一条提问发出去,光标转了两圈才吐出答案。用户不会关心模型参数有多少,只觉得“有点慢”。而机房里,GPU 利用率曲线并不好看——有时空转,有时排队。推理优化要处理的,正是这类不体面的日常。
慢在哪里,不只是模型大小
一次推理大致分成两段:预填充和逐 token 生成。前者更吃算力,后者更吃内存带宽。上下文一长,KV 缓存跟着膨胀;批处理能提升整体吞吐,却可能拉高单个请求的等待时间。量化能省显存和带宽,但输出稳定性需要重新验证。这些手段彼此牵连,很少能靠一个开关解决。
很多讨论习惯把“模型小”等同于“跑得快”,实际并不完全如此。小模型如果在长上下文里频繁重算,或者调度策略粗放,延迟照样会冒出来。
吞吐和延迟,常常不在一个方向
在线服务盯的是尾延迟,离线任务看的是总吞吐。把 batch 开大,单位时间能处理更多请求,但排在后面的用户要多等一会儿。连续批处理、前缀缓存这类手段,各自瞄准不同瓶颈。工程上先要问清楚:这个接口的等待预算是多少,超时之后怎么降级。没有这个前提,推理优化容易变成调参表演。
省下来的算力,未必等于省下来的钱
成本不只是 GPU 小时。扩缩容的响应速度、冷启动、模型版本切换、监控盲区,都会吃掉优化收益。有时把请求排队策略理清楚,比换一个更花的算子更有效。一个常见偏差是过度关注算子层面的微调,却忽略了缓存命中率和调度抖动。前者看起来技术含量高,后者往往更接近真实体验。
边界:别把优化做成另一种欠债
过度量化、过度批处理,可能让输出质量悄悄漂移,排查成本后移到业务侧。推理优化需要配套的可观测性:每段耗时、缓存命中、失败重试、降级次数,都得能看见。否则省下来的那点延迟,会在客服工单和人工复核里还回去。
还有一个容易被忽略的边界:优化手段和硬件、框架版本、流量形态强相关。别人的参数拿过来,未必能复现同样的效果。更稳妥的做法是小流量灰度,保留回退路径,把收益和风险一起计量。
回到那个光标转圈的夜晚。用户感知的是毫秒级的差别,工程师面对的是一串相互牵制的参数。推理优化更像持续校准,而不是一次性交付。当前业务能接受的平衡点,才是参数调整的起点。