LLM 延迟分解:为什么 TTFT 和吞吐量是两个不同的问题
大多数在 LLM 上构建应用的工程师都将延迟视为一个单一的刻度盘。他们调整一些参数——批处理大小(batch size)、量化级别(quantization level)或实例类型(instance type)——观察“它是否变快了”,然后就收工了。这在上线生产环境之前一直有效,直到你发现 p50 TTFT 看起来不错,而 p99 却超过了 3 秒,或者发现让吞吐量翻倍的优化不知为何却让单个用户感觉系统变慢了。
TTFT 和吞吐量(throughput)并不是同一个滑块的两端。它们是由根本不同的物理特性引起的,受不同瓶颈的影响,并由不同的技术修复。将它们视为可互换的是我在生产环境中看到的大多数 LLM 推理事故的根本原因。
每个 LLM 请求中隐藏的两个阶段
每个 LLM 请求都按顺序执行两个阶段,它们在计算上截然不同。
Prefill( 预填充)阶段在单次前向传递中处理整个输入 prompt。模型读取你发送的每一个 token,计算所有 token 的 attention(注意力),并构建一个在生成过程中使用的 KV (key-value) cache。这个阶段是 计算受限 (compute-bound) 的:它由 prompt 长度上的矩阵乘法主导,随着输入变长,其复杂度大约呈 O(n²) 增长。FLOPs 越多 = prefill 越快。首个 token 响应时间 (TTFT) 很大程度上取决于此——在这次传递完成之前,模型无法发出任何一个输出 token。
Decode(解码)阶段是生成发生的地方。模型以自回归的方式一次产生一个 token。每一步都将所有模型权重从 GPU 内存加载到计算中以计算单个 token。这个阶段是 内存带宽受限 (memory-bandwidth-bound) 的:瓶颈在于你从 HBM 读取几 GB 权重的速度,而不是你可以执行多少 FLOPs。吞吐量(throughput)——即系统每秒生成多少个 token——取决于此。
这就是核心矛盾:prefill 需要计算力,定期 decode 需要内存带宽。它们竞争相同的 GPU 资源。2024–2025 年的每一项重大推理优化——chunked prefill(分块预填充)、prefill-decode disaggregation(预填充-解码解耦)、speculative decoding(投机采样解码)——都是在尝试解决这种竞争,而不至于同时牺牲这两个指标。
总延迟公式为:
End-to-End Latency = TTFT + (TPOT × output_tokens)
其中 TPOT (time per output token) 是 每步解码的延迟。TTFT 和 TPOT 有不同的原因和不同的解决方法。
何时该关注哪个指标
在进行任何优化之前,请明确你的用户实际体验到的是哪个指标。
在以下情况下优化 TTFT:
- 用户正在看着光标或空白屏幕——聊天机器人、编程助手、语音代理
- 你正在运行代理循环 (agentic loops),其中每个工具调用的响应都会以乘法方式增加总任务延迟
- 延迟直接关系到金钱,例如在金融或交易应用中
人类感知研究给出了一个明确的阈值:TTFT 在 500ms 以下感觉响应迅速;超过 1,000ms 用户会有所察觉;超过 2,000ms 就会产生挫败感。MLCommons 在其 MLPerf 5.1 交互式场景中将此规范化:TTFT ≤ 500ms,TPOT ≤ 30ms(大约每秒 33 个 token,与典型阅读速度匹配)。在 TPOT 低于 30ms 时,进一步的解码速度提升是察觉不到的——用户阅读速度赶不上 token 生成的速度。
在以下情况下优化吞吐量(Throughput):
- 没有用户在盯着:文档摘要流水线、数据标注、夜间报告生成
- 每个 token 的成本驱动着业务模式——最大化 GPU 利用率以最小化支出
- 你正在生成合成训练数据或运行批量向量化(embedding)任务
在批处理工作负载中,接受几秒钟的 TTFT 通常没问题。优化的目标完全转向最大化单位美元生成的 token 数。
大多数团队犯的错误是在为批处理吞吐量调优的基础设施上运行具有交互感的产品,反之亦然。
你在生产环境中真正应该追踪的指标
永远不要在 TTFT SLO 管理中使用平均值。一个平均 TTFT 为 200ms 的系统,其 p99 可能同时达到 3,000ms——这意味着 1% 的用户等待的时间比平均值建议的长 15 倍。始终分别跟踪 p50、p95 和 p99。在 p50 保持稳定的情况下,p99 的恶化是排队积压或内存压力的早期预警。
第二个测量失败模式是在错误的并发级别下进行测试。在 1 个并发用户时的 TTFT 基本上只是网络延迟加上一次前向传递——它几乎不能说明任何生产环境的行为。请在预期的 p95 并发请求数下进行测试。Artificial Analysis 专门从事独立的 API 基准测试,他们转向使用 10k token 的默认 prompt,正是因为 1k token 的 prompt 掩盖了现实世界中的行为。
第三个指标值得跟踪的是 有效吞吐量 (goodput):即 TTFT 和 TPOT 均满足你的 SLO 目标的每秒请求数。一个达到 100 req/s 但其中 70% 的请求未能满足 TTFT SLO 的系统,其有效吞吐量仅为 30 req/s。原始吞吐量数字在新闻稿中看起来很棒;有效吞吐量才告诉你用户的真实体验。
针对 TTFT 的优化技术
KV 缓存前缀重用 (KV cache prefix reuse) 是大多数生产工作负载中收益最高的 TTFT 优化手段。如果你的系统提示词(system prompt)有 10,000 个 token,那么每一个命中热缓存(warm cache)的请求都能避免处理这些 token 所需的全部计算成本。Glean 的生产系统在缓存命中的请求中观察到 TTFT 从 4.3s 下降到 0.6s —— 在不改变模型的情况下实现了 7 倍的提升。LMCache 证明了 TTFT 可以提高 6.7 倍(从 1.2s 降至 0.18s),同时由于更好的缓存利用率,吞吐量提升了 80%。关键在于监测你的缓存命中率;那些部署了前缀缓存但未测量命中率的团队,只能获得一小部分潜在收益。
预填充-解码 (PD) 分离 (Prefill-decode disaggregation) 将预填充和解码运行在不同的 GPU 池上,消除了问题的根源 —— 阶段干扰。解码 GPU 永远不会因为等待预填充完成而停滞。在 OSDI 2024 上发表的 DistServe 证明,在 Llama-3.1-405B 上 TTFT 提升高达 7.66 倍,QPS 提升了 7 倍。到 2025 年中期,几乎所有主流框架(vLLM、SGLang、NVIDIA Dynamo、LMCache)都支持大规模部署的 PD 分离。一个警告:预填充和解码节点的最佳比例取决于工作负载。默认配置可能会导致 20–30% 的性能倒退;你需要根据实际的输入/输出长度分布来调整资源分配。
分块预填充 (Chunked prefill) 最初在 OSDI 2024 的 Sarathi-Serve 论文中提出,它将长提示词分解为 256–512 token 的块,并将它们与解码迭代交错进行。这消除了“解码停顿”—— 即单个大型预填充阻塞正在进行的解码步骤数秒的情况。权衡之处在于平均 TTFT 略有增加,以换取显著降低的尾部延迟和更高的吞吐量。Sarathi-Serve 证明,与基准 vLLM 相比,Mistral-7B 的服务能力提高了 2.6 倍,Yi-34B 提高了 3.7 倍。
缩短提示词长度 是一个虽然乏味但经常被忽视的手段。更短的提示词直接减少了预填充计算。在 RAG 工作负载中,提高检索质量 —— 返回更少、更相关的分 块 —— 在你动用任何基础设施开关之前,就能产生直接的 TTFT 优化效果。
针对吞吐量的优化技术
连续批处理 (Continuous batching)(Orca 算法,目前在生产服务中已普及)会在生成槽位释放时,动态地将新到达的请求添加到正在进行的批次中,而不是等待整个静态批次完成。结合 PagedAttention —— 它在非连续内存块中管理 KV 缓存以消除碎片化 —— 这是每个团队都应该运行的基准配置。vLLM 推广了这两者;它们现在已是标配。
量化 (Quantization) 以少量的模型质量损失换取巨大的吞吐量提升。FP8 权重和激活在 H100/Blackwell 上能提供约 2 倍的吞吐量,且质量损失极小。INT4/GPTQ 可以推动 3–4 倍的提升,但对质量更敏感。NVIDIA 在 2025 年推出的 NVFP4 KV 缓存格式,在大批次下与 FP8 KV 缓存相比,实现了 20% 更高的缓存命中率和 3 倍更低的延迟。
投机采样 (Speculative decoding) 在低到中等并发情况下利用空闲计算资源,运行一个小型的草案模型(1–7B 参数)每步生成 3–12 个候选 token。目标模型在一次并行处理中验证它们,当草案模型正确时,能以一次解码步骤的代价获得多个 token。TensorRT-LLM 报告了高达 3.6 倍的吞吐量提升;使用 DeepSeek 模型的 vLLM 显示每 token 延迟降低了高达 50%。但这里有一个关键的反转:在高并发情况下,草案模型会与真实的推理请求争夺 GPU 资源,此时投机采样会 损害 吞吐量。它主要是低并发下的延迟优化。其性能反转的并发阈值取决于模 型和硬件 —— 请根据你的工作负载进行测量。
数据并行 (Data parallelism)(在负载均衡器后跨 GPU 实例复制模型)是水平扩展吞吐量的粗暴但有效的策略。它随 GPU 数量线性扩展,成本也线性增加 —— 没有免费的午餐,但它确实奏效。
框架与供应商选择
服务框架的选择对 TTFT 与吞吐量的权衡影响比大多数团队意识到的要大。
vLLM 仍然是自托管服务的行业标准:广泛的模型支持,默认支持连续批处理和 PagedAttention,活跃的社区。它是最稳妥的基准选择。HuggingFace TGI v3 在低并发下的 TTFT 表现经常优于 vLLM —— 在启用前缀缓存的长上下文工作负载中快达 13 倍 —— 但 vLLM 通常在高并发吞吐量方面获胜(在某些基准测试中有 2–24 倍的优势)。TensorRT-LLM 在 NVIDIA 硬件上提供最高的原始吞吐量,但需要模型编译且仅限 NVIDIA。SGLang 已成为推理模型和复杂 Agent 工作流的最佳选择,特别是针对像 DeepSeek 这样的 MoE 架构。
对于云端 API,选择范围很广。Groq 基于 LPU 的推理在权重开放模型上始终保持亚 100ms 的 TTFT 和 750–1,580 token/s 的成绩 —— 吞吐量比基于 GPU 的供应商快约 20 倍,TTFT 低 3–4 倍。限制在于模型覆盖范围:仅限权重开放模型,不支持微调。在 H100 上的 GPU 云供应商对于 10k token 的提示词,在低并发下通常能达到 200–800ms 的 TTFT。独立基准测试 (Artificial Analysis) 显示,各供应商的 TTFT 范围在 0.27s 到 4.5s 之间,输出速度在 313 到 900+ TPS 之间 —— 存在一个 数量级的差异。
决策矩阵
这是实际的决策框架:
如果你正在构建一个交互式产品——聊天、编程助手、语音智能体、智能体循环——你的首要目标是在 p95 并发水平下实现 TTFT < 500ms。从前缀缓存(prefix caching)命中率开始;先解决这些问题。然后在真实的负载下进行基准测试,找到你实际的瓶颈(队列深度、prefill 成本或 decode 停顿)。当服务吞吐量需求很高且交互延迟同时不可妥协时,PD 分离(PD disaggregation)和分块预填充(chunked prefill)是架构层面的解决方案。
如果你正在运行批处理工作负载——流水线、标注、合成——应最大限度地提高 GPU 利用率和单位美元的输出 token 数。使用大 batch size 的连续批处理(Continuous batching)、量化以及充足的 KV 缓存预算。接受更高的 TTFT。如果你没有 SLO(服务水平目标),那么在 SLO 下的有效吞吐量(Goodput)就毫无意义。
如果你是从云 API 供应商那里购买服务,你可以在投入使用之前,针对你预期的 prompt 长度对 TTFT 进行基准测试。Artificial Analysis 和类似的服务会发布独立的测评数据;利用好它们。
大多数团队容易犯的错误
错误往往遵循一定的模式。最常见的是优化平均延迟而不是 p99——在出现长 prompt 或队列峰值揭示实际的长尾延迟之前,系统看起来表现良好。其次是在单个 并发用户下进行基准测试:除非你的生产环境流量真的只有一个用户,否则这个数字毫无意义。
将原始吞吐量视为用户体验的代名词是一个更微妙的错误。一个达到了 1,000 tokens/second 但大多数请求都违反了 TTFT SLO 的系统,对用户来说表现并不好。有效吞吐量(Goodput)才是正确的指标;请明确追踪它。
硬件选择经常存在盲目跟风(cargo-culting)。H100 并不总是正确答案。对于中等并发下的较小模型,A10G 或 L4 实例通常能提供更好的成本效率。H100 的 HBM3 带宽优势对于受内存带宽限制(memory-bandwidth-bound)的 decode 阶段很重要;对于受计算限制(compute-bound)的 prefill 阶段,其成本溢价通常并不值得。
最后:启用投机解码(speculative decoding),观察到 TTFT 有所改善,宣布成功——然后忽略了你已经在峰值负载下悄悄降低了吞吐量。草稿模型(draft model)的运行并不是免费的。
核心洞察
Prefill 是受计算限制的(compute-bound)。Decode 是受内存带宽限制的(memory-bandwidth-bound)。鉴于当前的 GPU 架构,这些事实是不可改变的。你应用的每一项优化,要么减少了其中一个阶段的工作量,要么将两个阶段分开以防止干扰,要么利用一个阶段的空闲资源来加速另一个阶段。
了解在你实际的生产并发下哪个阶段是你的瓶颈,就能告诉你该采用哪类优化方案。如果找错了类别,你将会在那些无法在生产环境中体现出来的改进上浪费工程时间——或者更糟,以牺牲用户感知到的指标为代价,去换取一个仅在基准测试中好看的指标。
- https://docs.anyscale.com/llm/serving/benchmarking/metrics
- https://www.ibm.com/think/topics/time-to-first-token
- https://bentoml.com/llm/inference-optimization/llm-inference-metrics
- https://bentoml.com/llm/inference-optimization/prefill-decode-disaggregation
- https://www.clarifai.com/blog/ttft-vs-throughput
- https://arxiv.org/pdf/2401.09670
- https://www.usenix.org/system/files/osdi24-agrawal.pdf
- https://developer.nvidia.com/blog/tensorrt-llm-speculative-decoding-boosts-inference-throughput-by-up-to-3-6x/
- https://www.glean.com/blog/glean-kv-caches-llm-latency
- https://blog.lmcache.ai/2025-03-31-eurosys/
- https://modal.com/blog/vllm-vs-tgi-article
- https://arxiv.org/html/2410.14257v1
- https://groq.com/blog/artificialanalysis-ai-llm-benchmark-doubles-axis-to-fit-new-groq-lpu-inference-engine-performance-results
- https://llm-d.ai/blog/kvcache-wins-you-can-see
- https://www.runpod.io/articles/guides/llm-inference-optimization-playbook
