在大语言模型推理系统中,Batch Size是最容易被简单化理解的参数之一。很多人认为GPU本来就适合并行计算,所以一次塞进去的请求越多,GPU利用率越高,单个请求的推理速度也应该越快。实际部署往往不是这样。Batch Size增大通常有利于提高整体吞吐量,但并不意味着每一个用户的等待时间都会下降。在某些情况下,批量继续增大以后,GPU吞吐量仍然增加,而单请求延迟已经明显上升。
这背后的原因并不是某一个硬件参数,而是模型计算、显存容量、显存带宽、KV Cache、GPU并行度、请求长度以及调度策略共同作用的结果。对于现代LLM服务,还必须区分prefill和decode两个阶段,否则很容易把不同性质的计算混在一起。
先理解Batch Size究竟是什么。
最简单的静态Batch可以理解为一次把多个独立输入组成一个批次交给模型处理。例如Batch Size为1时,GPU处理一个请求;Batch Size为8时,同时处理8个请求。
在传统深度学习训练中,Batch Size通常比较容易理解,因为一批样本进入模型后,计算图结构相对稳定。但LLM在线推理复杂得多。不同用户的输入长度可能完全不同,输出长度也不同,而且每个请求生成token的速度并不一致。因此现代LLM服务通常不会简单地等待固定数量的请求凑齐以后一次性处理,而会采用continuous batching,也就是动态地把正在运行和新进入的请求组织到GPU计算中。
这意味着工程人员讨论Batch Size时,首先要问清楚:说的是静态batch、动态batch、并发请求数,还是某个时刻实际参与计算的序列数量。它们不是完全相同的概念。
LLM推理还需要把prefill和decode分开。
用户输入的prompt首先需要经过prefill阶段。这个阶段需要处理输入中的大量token,并建立后续生成所需的KV Cache。输入很长时,prefill可能产生相当大的计算量,而且GPU通常能够利用更高的矩阵计算并行度。
进入decode阶段以后,模型通常一次生成一个或少量新token。每生成一个token,都需要结合此前保存的KV Cache继续计算。因此decode的性能特征与prefill并不一样。
这也是为什么单纯讨论“Batch Size越大越快”容易产生误导。增加Batch可能让GPU在decode阶段同时服务更多序列,从而提高整体tokens/s,但每一个请求仍然需要等待更多序列共同占用计算和显存资源。吞吐量提高与单请求延迟下降完全可以同时不成立。
对于在线AI服务来说,至少应该同时观察TTFT、ITL、吞吐量以及P95和P99延迟。
TTFT,也就是Time To First Token,主要反映用户从提交请求到看到第一个生成token所等待的时间。prefill、排队和调度都会影响这个指标。
ITL,也就是Inter-Token Latency,反映生成过程中相邻token之间的等待时间。decode阶段的计算和调度对它影响很大。
吞吐量则可以使用tokens/s或者requests/s等指标衡量。一个Batch Size从8增加到16后,整个GPU集群每秒生成的token数量可能提高,但用户看到第一个token的等待时间也可能增加。
所以AI推理系统真正需要优化的通常不是一个孤立的“最快Batch Size”,而是在目标SLO下寻找吞吐量与延迟之间的平衡点。
显存容量是Batch Size的重要限制因素,但KV Cache的计算也不能简单理解为“Batch增加一倍,KV Cache就一定增加一倍”。
对于相同模型、相同精度、相同序列长度以及相同KV配置,如果同时运行的序列数量增加,那么KV Cache总体占用通常会随活动token数量增加。工程上更准确的概念是active tokens,而不是只看Batch Size。
例如,两个Batch都包含16个请求,其中一个批次每个请求只有500个token,另一个批次每个请求已经生成到8000个token,两者需要的KV Cache完全不是一个数量级。
因此,推理服务实际需要监控的是KV Cache占用、活动序列数量、每个请求的上下文长度以及可用显存,而不能只设置一个“Batch Size最大值”。
当KV Cache不断增长并接近显存容量时,系统可能不得不降低并发度、等待请求完成,或者采用更复杂的内存管理方式。如果部署系统涉及GPU之间的模型分片,还可能进一步引入跨卡通信和调度开销。
显存带宽同样非常重要,但不能简单用“超过80%就是瓶颈”这种固定阈值判断。
现代GPU在LLM decode阶段经常受到显存访问效率和内存带宽的影响,因为每生成一个token都需要访问模型权重以及大量KV Cache。增加Batch以后,部分矩阵计算能够得到更高利用率,但与此同时需要处理更多序列和KV数据。
如果GPU已经受到内存带宽限制,继续增加Batch未必能够带来同比例的性能提升。GPU可能从原来的计算受限逐渐转变为内存受限,或者反过来出现其他资源瓶颈。
因此专业性能分析通常会结合HBM带宽利用率、Tensor Core利用率、SM占用率、显存占用、memory stalls、kernel执行时间以及tokens/s等指标,而不是拿一个固定百分比作为判断标准。
GPU计算能力也不是随着Batch Size简单线性增加。
当Batch较小时,GPU可能没有足够多的并行工作填满Tensor Core和SM。增加Batch以后,可以让矩阵乘法形成更大的计算规模,从而提高硬件利用率。
但是这种提升存在上限。
当GPU已经接近计算能力、显存带宽或者其他硬件资源的限制以后,继续增加Batch不会继续产生同等比例的收益。此时更多请求只能排队或者共享已经饱和的计算资源。
这就产生了一个非常重要的工程现象:Batch Size增加以后,GPU利用率可能继续提高,但用户体验却开始变差。
原因很简单。GPU利用率是整个设备的资源指标,不是某一个用户请求的等待时间指标。
如果一个GPU原来只有20%的有效计算利用率,同时处理更多请求以后达到70%,整体吞吐量通常会明显改善。但从70%继续压到95%,增加的吞吐量可能已经越来越有限,而队列等待时间和尾延迟却可能明显增加。
因此不能看到GPU利用率不高就无限增加Batch,也不能看到GPU利用率很高就认为系统已经优化完成。
模型并行方式同样会影响Batch Size的收益。
如果模型可以完整放入一张GPU,增加并发请求主要涉及该GPU内部的计算、显存和调度资源。
如果模型太大,需要进行tensor parallel或者其他形式的模型分片,则一次推理可能涉及多张GPU。此时Batch Size增加可以提高计算利用率,但每轮计算同时也可能需要更多GPU之间的通信。
通信并不等于一定会成为瓶颈。具体影响取决于模型结构、并行方式、GPU之间的互联拓扑、消息大小、通信重叠能力以及serving框架的实现。
NVLink、NVSwitch和PCIe在不同硬件平台上的通信能力也不同。不能简单拿某一代NVLink的理论带宽套到所有NVIDIA GPU上,更不能认为“有NVLink就可以随便扩大Batch”。
如果模型使用多卡tensor parallel,还需要观察collective communication,例如All-Reduce等操作是否开始占据明显的执行时间。
模型复制和模型分片也应该区分。
如果一个模型能够放入单张GPU,但单卡吞吐量不够,可以复制多份模型,让不同请求分散到不同GPU上。这种情况下增加GPU数量主要是提高整体服务容量。
另一种情况是模型本身无法放入单张GPU,需要将模型切分到多张GPU上。此时增加GPU并不是简单增加几个独立的服务实例,而是改变了单个请求的执行方式。
这两种架构对于Batch Size和延迟的影响完全不同。
实际部署中还存在一个非常重要的问题,就是请求长度不一致。
假设一个batch里有16个请求,其中几个请求只有几十个输入token,而另外几个请求拥有数万token,那么系统需要面对明显的长度差异。传统静态batch如果简单进行padding,会产生大量无效计算。
现代推理框架通常会采用更灵活的batch调度和KV Cache管理机制,尽量减少padding带来的浪费,并让新请求在已有请求生成过程中进入计算批次。
这正是continuous batching的重要价值。
它不是简单地把Batch Size从8改成16,而是让调度器根据当前GPU状态、请求长度、KV Cache空间和生成进度动态决定哪些序列参与下一轮计算。
因此,现代LLM服务更适合从“每一批有多少请求”转向“每一步有多少活动token和序列参与计算”来理解性能。
量化也会改变Batch Size的最佳区间。
FP16、BF16、FP8、INT8以及其他量化方式会改变模型权重和部分中间数据的存储规模,同时也可能改变GPU计算路径、显存访问量以及Tensor Core的利用方式。
模型从FP16降低到FP8或者INT8以后,确实可能降低显存占用并提高某些硬件上的计算效率,但不能直接认为量化比例是多少,性能就会提高多少。
不同模型、不同GPU、不同kernel实现以及不同Batch Size下,收益可能完全不同。
尤其需要注意,量化首先解决的是模型权重和相关数据的存储与计算问题,并不意味着KV Cache、通信和调度开销会按照同样比例下降。
所以工程人员在测试量化方案时,应该同时重新测量TTFT、ITL、tokens/s、显存占用以及P95/P99延迟,而不是只看模型文件从多少GB减少到多少GB。
实际工程中的最佳Batch Size通常不是一个固定数字。
例如一个模型在某张GPU上Batch Size为1时吞吐量很低,增加到4以后性能大幅改善,增加到8以后继续改善,到了16以后收益开始变小,32以后GPU已经受到显存带宽、KV Cache或者计算资源限制,64以后P99延迟快速上升。
这种情况下,32未必是最佳配置。真正的最佳点取决于业务目标。
如果这是离线批处理任务,用户并不关心单个请求等待几秒钟,那么可以更加激进地提高Batch,尽可能追求tokens/s。
如果这是在线聊天服务,用户希望快速看到第一个token,那么TTFT和P99延迟可能比峰值吞吐量更加重要。
如果这是企业API服务,则还要考虑不同租户的SLO、请求优先级、最大上下文长度、GPU显存余量以及突发流量。
因此,一个成熟的推理系统通常不会只有一个Batch Size参数,而会同时存在最大并发序列数、最大批次token数、最大等待时间、KV Cache容量以及调度策略等多个控制条件。
这也是为什么实际部署时,“把Batch Size调到最大”经常不是一个好主意。
如果请求不断进入系统,而调度器为了凑满Batch一直等待更多请求,单个用户的TTFT可能反而增加。反过来,如果完全不等待,Batch长期保持很小,GPU又无法获得足够的并行度,整体吞吐量会下降。
工程上通常需要在有限的等待时间内尽可能形成有效批次,同时避免因为等待凑批而牺牲用户体验。
这也是动态batch调度最有价值的地方。
如果把LLM推理看成一条生产线,GPU并不是“人越多越快”的无限容量机器。少量请求进入时,生产线可能没有充分利用;请求增加以后,设备开始发挥并行计算能力;继续增加请求以后,显存、带宽、计算单元、通信链路和调度队列逐渐达到瓶颈。再往上压,吞吐量的增长越来越有限,而等待时间却可能快速增加。
因此,Batch Size优化的核心并不是寻找一个最大的数字,而是找到当前模型、GPU、上下文长度、量化方式和业务SLO共同决定的工作区间。
在实际性能测试中,建议至少记录Batch Size、active sequences、active tokens、KV Cache占用、GPU显存、HBM带宽、SM利用率、Tensor Core利用率、TTFT、ITL、输入tokens/s、输出tokens/s以及P50、P95、P99延迟。
只有把这些指标放在一起观察,才能知道问题到底出在计算、显存、通信还是调度。
AI推理的性能优化最终不是一个“Batch Size越大越好”的数学题,而是资源调度问题。小Batch可能浪费GPU并行能力,大Batch可能增加KV Cache压力、内存访问和排队等待;模型分片可能增加通信,模型复制则主要改变整体服务容量;量化可以降低部分资源压力,却不会自动消除所有瓶颈。
对于在线LLM服务,最值得追求的通常不是某一次测试中最高的GPU利用率,而是在可接受的TTFT、ITL和P95/P99延迟下,获得尽可能高的稳定吞吐量。能够在这个范围内持续运行的Batch配置,才是生产环境真正有价值的配置。
AI 推理中的 Batch Size 应该怎样理解,批量增大后为什么延迟不一定更低
喜欢这篇报道?
使用下面的功能,方便以后继续阅读和分享 MNewsTV
关于文章收藏
收藏不需要注册帐号,收藏信息仅保存在当前浏览器中。
删除收藏请进入「我的收藏」进行管理。
捐助(Paypal): https://www.paypal.me/observeccp 订阅中国观察电报 Telegram : https://t.me/s/ObserveCCP