3、推理速度基础:吞吐量与延迟、首Token延迟(TTFT)与Token间延迟(ITL)、批处理(Batching)原理
聊到vLLM推理,大家最关心的无非两个事:快不快,以及稳不稳。快,指的是吞吐量高、延迟低;稳,指的是首Token别卡太久,后续Token也别忽快忽慢。
我个人习惯把推理速度拆成三个维度来看:吞吐量、延迟、批处理效率。这三个东西互相牵制,你调好一个,另一个可能就崩了。今天咱们就把它们掰开揉碎讲清楚。
3.1 吞吐量与延迟:一对天生的冤家
先说吞吐量。说白了,就是单位时间内能处理多少个请求。比如你的服务每秒能处理100个请求,那吞吐量就是100 req/s。vLLM里常用的是每秒输出Token数(Tokens per second)。
延迟呢?就是一个请求从发出去到拿到完整回复的时间。用户感知最直接的就是这个。
你想想看,吞吐量和延迟是不是天生矛盾?你拼命塞请求进去,吞吐量上去了,但每个请求排队时间变长,延迟就飙升。反过来,你只处理一个请求,延迟很低,但吞吐量惨不忍睹。
我在项目中遇到过这种情况:为了追求高吞吐,把batch size拉到最大,结果单个请求的延迟从200ms飙到2秒。用户直接投诉“卡死了”。所以调优时,你得先明确业务场景——是聊天场景(低延迟优先)还是离线批量处理(高吞吐优先)。
吞吐量 = 总输出Token数 / 总耗时
平均延迟 = 所有请求延迟之和 / 请求数
3.2 首Token延迟(TTFT)与Token间延迟(ITL)
这两个指标,是vLLM调优里最容易被忽视的细节。我刚开始做推理优化时,只盯着总延迟看,结果发现用户反馈“打字半天才出第一个字”。这就是TTFT的问题。
3.2.1 首Token延迟(TTFT)
TTFT,全称Time to First Token。指的是从请求发出到模型输出第一个Token的时间。这个时间主要花在:
- Prefill阶段:模型处理输入Prompt,计算KV Cache
- 网络传输:请求从客户端到服务端的往返
- 调度排队:请求在vLLM调度器里等待被处理
我记得有一次,用户反馈某个大模型“反应慢”,我查了半天,发现是Prompt太长(超过2000 Token),Prefill阶段耗时占了TTFT的80%。后来我建议用Prompt压缩或分块Prefill,TTFT直接降了60%。
3.2.2 Token间延迟(ITL)
ITL,Inter-Token Latency。指的是相邻两个Token输出之间的时间间隔。这个指标直接决定了“打字速度”的流畅感。
ITL主要受Decode阶段影响。Decode阶段是自回归的——每生成一个Token,都要重新计算一次。vLLM通过KV Cache和PageAttention来加速,但ITL依然受限于:
- Batch size:batch越大,每个Token的计算时间越长
- 模型大小:7B模型ITL通常在10-20ms,70B模型可能到50-100ms
- 显存带宽:Decode阶段是显存带宽瓶颈,不是算力瓶颈
你想想看,如果ITL是50ms,那每秒只能输出20个Token,用户会觉得“一个字一个字往外蹦”。我建议把ITL控制在30ms以内,这样用户体验才过得去。
3.3 批处理(Batching)原理
批处理是vLLM提升吞吐量的核心手段。但批处理不是简单的“把多个请求塞一起算”,这里面门道很多。
3.3.1 静态Batching vs 动态Batching
静态Batching:把所有请求收集齐了,一次性算完。优点是实现简单,缺点是等待时间长——你得等最后一个请求到了才能开始算。
动态Batching:来一个请求就处理一个,不等。vLLM用的是Continuous Batching(连续批处理),这是它的杀手锏。
Continuous Batching的原理是:每个请求独立进行Prefill和Decode,但共享GPU计算资源。比如请求A在做Prefill时,请求B已经在Decode了。这样GPU始终处于忙碌状态,不会因为等待而闲置。
我记得第一次看到Continuous Batching的效果时,挺震撼的。同样的硬件,静态Batching的吞吐量只有200 Token/s,换成Continuous Batching直接飙到800 Token/s。说白了,就是把GPU的空闲时间压榨到了极致。
3.3.2 Batch Size的选择
Batch size不是越大越好。我建议你根据显存大小和模型大小来定。一个经验公式:
最大Batch Size = (可用显存 - 模型权重显存) / (每个请求的KV Cache显存 + 激活显存)
举个例子,一张A100 80GB显卡,部署7B模型(权重约14GB),每个请求的KV Cache约2GB(假设序列长度4096)。那么:
可用显存 ≈ 80GB - 14GB = 66GB
每个请求显存 ≈ 2GB + 0.5GB(激活)= 2.5GB
最大Batch Size ≈ 66 / 2.5 ≈ 26
但实际中,我建议留20%的余量,所以Batch Size设到20左右比较安全。
TTFT看Prefill,ITL看Decode
Batch Size看显存,Continuous Batching保吞吐
3.4 知识体系图:推理速度核心指标
下面这张图,是我自己总结的推理速度调优框架。你可以把它当成一个检查清单,每次调优时对照着看。
3.5 实战建议:如何平衡这三个指标
说了这么多理论,最后给点实战建议。我自己的调优流程是这样的:
- 先定延迟目标:比如TTFT不超过500ms,ITL不超过30ms。这是硬约束。
- 再调Batch Size:从1开始往上加,直到TTFT或ITL超标为止。这个临界点就是最优Batch Size。
- 开启Continuous Batching:vLLM默认就是,但要注意调度策略。如果并发高,建议用优先级队列。
- 监控显存:用
nvidia-smi或vLLM自带的metrics,看显存是否打满。如果显存有剩余,可以继续加Batch Size。 - 反复迭代:调优不是一次性的。业务高峰期和低谷期,参数可能不一样。我建议写个自动调优脚本,定期跑压力测试。
嗯,以上就是推理速度基础的全部内容。吞吐量、延迟、批处理,这三者就像三驾马车,你得让它们齐头并进。下一节咱们会深入KV Cache与PageAttention,那是vLLM提速的核心秘密。
公众号:蓝海资料掘金营,微信deep3321