← 返回题目列表

推理吞吐和延迟为什么经常冲突?

中等 第 25 / 25 题 更新于 2026/09/17
大模型推理优化AI技术大模型面试题

简化版

吞吐衡量单位时间完成的请求或生成的 Token,延迟衡量单个请求等待多久。为了提高吞吐,系统会等待凑批并让更多序列共享一次权重读取;这提高 GPU 利用率,却增加排队时间、资源竞争和单轮执行时间,所以延迟尤其是 P99 往往上升。

正确目标不是单独最大化某一个指标,而是在 TTFT、TPOT 和端到端 SLO 约束下最大化“有效吞吐”。做法包括连续批处理、Token 预算、准入控制、优先级队列和基于真实流量的容量规划。

详细版

大模型在线推理至少有三类延迟:排队时间、Prefill 首 Token 时间、Decode 每 Token 时间。增大 Batch 能摊薄权重读取和 Kernel 启动,提高总 Tokens/s;但等待凑批会增加排队,更大的计算批次也可能让每次迭代变长。

这是一条排队系统的基本规律:到达率接近服务容量时,利用率继续升高,等待时间会非线性恶化。因此生产服务应预留余量,而不是长期把 GPU 压到理论满载。

业务首要约束合适策略
实时聊天TTFT、TPOT P95/P99小等待窗口、连续批处理、限流
离线生成完成时间、单位成本大 Batch、队列聚合、低优先级
混合流量实时 SLO 与总吞吐分池、优先级、配额和抢占

调优时固定真实输入/输出长度分布,逐级提高并发,画出吞吐—延迟曲线,选择仍满足 SLO 的拐点;不能拿短 Prompt 的峰值 Tokens/s 代替线上容量。

完整版教学

1. 先把指标定义清楚

吞吐可以是 Requests/s,也可以是输入或输出 Tokens/s;延迟则至少包括 TTFT、TPOT 和端到端完成时间。不同定义回答的是不同问题,不能混用一个数字。

端到端延迟 = 排队 + Prefill + Decode + 网络/后处理
TTFT        = 排队 + Prefill + 首 Token 传输
TPOT        ≈ Decode 阶段相邻输出 Token 的平均间隔

聊天用户更敏感于 TTFT 和 TPOT,批量摘要任务则更关心整批完成时间与单位 Token 成本。

2. 为什么 Batch 会提高吞吐

Decode 单请求每步只处理一个 Token,却需访问大量模型权重。把多个请求合成 Batch,可以让一次权重读取服务更多 Token,提高算术强度并摊薄 Kernel 启动成本。

但 Batch 不是免费形成的:系统可能要等待更多请求到达,而且每轮处理的序列越多,执行时间和 KV 读写也越大。这就是吞吐收益与延迟代价的直接来源。

3. 排队为何会在高利用率下恶化

设平均到达率为 λ,平均服务率为 μ,利用率 ρ = λ / μ。在最简单的 M/M/1 直觉模型中:

平均系统时间 W = 1 / (μ - λ)

λ 接近 μ,分母趋近于零,等待时间急剧增加。真实 GPU 服务更复杂,但“长期满载会牺牲尾延迟”这一结论依然成立。

4. 为什么只看平均延迟不够

平均值可能很好看,但少量超长 Prompt、长输出或瞬时流量会制造 P99 尖峰。用户体验和上游超时通常由尾部决定,因此容量评估必须报告分位数。

例如平均 TTFT 为 600 ms、P95 为 1.8 s、P99 为 7 s,这不是“延迟约 600 ms”,而是服务在高压或长请求下缺少稳定性。还应按租户、长度桶和优先级拆分。

5. 静态批处理与连续批处理

静态批处理等整批请求一起开始并结束,短请求必须等待最长请求,适合长度相近的离线任务。连续批处理在迭代边界移出完成请求并补入新请求,更适合输出长度不可预测的在线生成。

模式吞吐在线延迟适用场景
单请求低负载下最小调试、极低流量
静态 Batch受最长请求拖累离线同质任务
连续 Batch高且利用稳定调度可控在线 LLM 服务

连续批处理仍需最大 Token 预算,否则新请求不断加入会把显存和每步耗时推高。

6. 等待窗口如何取舍

调度器可以等待 w 毫秒收集更多请求。较大的 w 提高成批概率,但这段时间直接计入 TTFT;在低流量期,等待可能没有换来任何批次收益。

更合理的策略是自适应:高峰时请求自然成批,等待窗口可缩短;低峰时若 SLO 严格则立即执行。离线队列可以使用更长窗口,因为其目标是吞吐和成本。

7. Token 预算比请求数更准确

一个 100 Token 请求和一个 20,000 Token 请求对 Prefill、KV Cache 和执行时间的影响完全不同。只限制 Batch 请求数会让资源使用剧烈波动。

调度时通常同时约束本轮 Prefill Token、活跃 Decode 序列、KV 块数和最大总 Token。必要时将超长请求放入独立队列,避免 Head-of-Line Blocking。

8. 吞吐应定义为有效工作

峰值 Tokens/s 可能包含之后被取消的输出、无价值的超长回答或因超时而重试的请求。业务真正需要的是成功任务吞吐:

effective throughput = successful_requests / wall_clock_time
cost per success = total_compute_cost / successful_requests

如果为了提高 Token 吞吐导致错误、超时和重试增多,硬件数字上涨但业务容量反而下降。

9. 准入控制为何不可缺少

当队列已经超过安全水位,继续接收所有流量只会让每个请求都超时。准入控制依据预测 Token、当前 KV 水位、优先级和截止时间,选择接收、排队、降级或拒绝。

合理拒绝比“接收后超时”更可控。客户端能快速重试到其他集群,服务端也能保护正在执行的高价值请求,避免过载雪崩。

10. 如何隔离在线与离线流量

离线任务可接受分钟级等待,在线聊天可能要求秒级首 Token。两者共享无配额队列时,大批离线请求会挤占在线 SLO。

可以采用独立实例池,或在共享池中设置优先级、租户配额、并发上限和老化机制。优先级不能无限压制低优先任务,否则会产生饥饿;应为每类流量定义最低服务份额。

11. 怎样寻找容量拐点

使用真实长度分布与到达过程,从低并发逐级加压,记录每档的输出 Tokens/s、Requests/s、TTFT、TPOT、P99、拒绝率和显存。吞吐开始趋平而尾延迟明显上升的位置就是饱和区。

生产容量应选在饱和点之前并留出故障余量。例如单副本在 P99 SLO 内能稳定承载 20 req/s,不能因为短时跑到 25 req/s 就按后者规划。

12. 自动扩缩容看什么信号

只看 GPU 利用率容易误判:Decode 可能受显存带宽限制,计算利用率并不满;扩容又有模型加载和预热延迟。更实用的信号包括队列 Token、预测等待时间、KV 使用率和 SLO 违约趋势。

扩容阈值要早于超时点,缩容则应更保守,并先排空实例。若冷启动需要数分钟,还应保留暖副本或按流量周期预扩容。

13. 如何做实验与上线守护

每次只改变批次上限、等待窗口或调度策略中的一个主要变量,并以同一流量回放比较。除了性能,还应确认请求顺序、公平性和生成质量没有因截断或抢占退化。

上线采用小流量灰度,设置 P99、拒绝率、OOM 和单位成功成本阈值。调度参数也必须版本化并可快速回滚,不能只保留模型版本。

最优吞吐不是 GPU 跑出的最大数字,而是在用户延迟目标、失败率和成本边界内能够长期维持的服务能力。

14. 常见误区与追问

  • 误区:GPU 利用率越接近 100% 越好。 长期满载会让排队和尾延迟失控,也没有故障余量。
  • 误区:Batch 越大,单位请求延迟越低。 它通常提高总吞吐,却增加等待和资源竞争。
  • 误区:Tokens/s 可以直接代表业务吞吐。 超时、取消和无效输出不应算成功任务。
  • 误区:平均延迟达标就满足 SLA。 用户和上游超时通常受 P95/P99 支配。
  • 误区:在线与离线请求放同一队列最省资源。 缺少隔离会让不同 SLO 相互伤害。
  • 追问:为什么高并发下延迟突然变差? 到达率逼近服务率后,队列等待会非线性增长。
  • 追问:应优先优化吞吐还是延迟? 先确定业务 SLO,再在该约束内最大化有效吞吐。

15. 加强记忆

  1. 先分指标:Requests/s、Tokens/s、TTFT、TPOT、端到端延迟。
  2. 再记收益:Batch 摊薄权重读取和 Kernel 开销。
  3. 再记代价:凑批等待、每轮变长、KV 竞争。
  4. 再记规律:利用率接近饱和,排队和 P99 急剧上升。
  5. 再记控制:Token 预算、连续批处理、准入与隔离。
  6. 再记容量:在真实流量曲线的饱和点之前留余量。
  7. 最后记目标:在延迟 SLO 下最大化成功任务吞吐。