一、输入长度不均:批处理优化的隐秘陷阱
大模型推理服务的请求在输入长度上呈现出极高的不均衡性。一个包含数千字背景知识的复杂查询,其输入token数可能高达8K甚至32K;而一个简单的短语提问可能仅有几十个token。两种请求同时到达时,批处理器面临根本性决策困境。
批量处理的收益来源于将多个请求的token合并为同一批次,共享显存读取带宽。但当批次中混入一个超长序列时,该序列的KV缓存占据大量显存,迫使批大小缩减。若为了迁就超长序列而缩小批大小,短序列请求的计算密度下降,GPU核心的利用效率受损;若为了利用短序列请求填充批大小,又可能导致超长序列与过多短序列共享批次,显存带宽在大量请求间分散,超长序列的生成时延被显著拉长。
我们的监控数据显示,在输入长度变异系数(标准差/均值)低于0.3的均匀分布下,固定批容量可达到较高的吞吐水平;但当变异系数超过0.6后,固定批容量的吞吐量下降幅度可达40%以上,且P99时延的波动幅度同步扩大。这说明输入长度分布的不均不仅是一个数据特征问题,更是批处理优化的核心约束变量。
二、长度分布感知:从静态配额到动态识别
要动态调节批容量,首先需要实时感知输入长度分布的统计特征。我们构建了一个轻量级的请求队列分析器,在每个调度周期(默认5秒)内扫描等待队列中的请求,统计三个关键指标:输入长度的中位数、P90分位数以及变异系数。
三个指标共同刻画了当前请求队列的长度分布形态。中位数反映典型请求的长度水平,决定批容量的基准;P90分位数揭示是否存在显著的长尾超长请求;变异系数则衡量整体的不均衡程度——变异系数越大,说明队列中长短请求的混合程度越严重,越需要精细化的批容量调节。
分析器的输出并非简单的统计数字,而是一个“分布形态标签”,将当前队列标注为四类之一:均衡型(变异系数<0.3)、轻度偏斜型(0.3至0.6)、重度偏斜型(0.6至0.9)和极端混合型(>0.9)。标签直接驱动后续的批容量计算逻辑。
三、批容量计算:显存与计算的双约束模型
动态批容量的最优值并非越大越好,也非越小越稳,而是在显存占用与计算密度之间寻找平衡点。我们建立了双约束模型来求解这一平衡。
显存约束:批次中所有请求的KV缓存大小之和不得超过预留给KV缓存的总显存空间。KV缓存大小与序列长度呈正比,若队列中存在多个超长请求,显存约束将直接限缩批大小。
计算密度约束:批次中token总数(所有请求的输入+输出长度之和)需达到一个“有效阈值”才能充分利用GPU的计算资源。若token总数过低,GPU核心的空闲时间占比过高;若token总数过高,则可能因显存带宽争抢而拖慢每个请求。
双约束模型在每个调度周期内求解:先根据显存约束计算理论上限,再根据计算密度约束计算理论下限,最终批容量在上下限之间选取。求解结果是一个浮动区间而非单一数值——例如,在当前队列分布下,批容量可在4至12之间选择,系统根据当前负载压力选择区间的上端(高吞吐优先)或下端(低时延优先)。
批容量不是每个批次都重新计算,而是以每5秒为周期更新一次,且相邻周期之间的变化幅度限制在±2以内。这一平滑策略防止了批容量在相邻批次间频繁跳变引发的调度抖动。
四、虚拟批切分:化解超长请求阻塞
即便批容量已根据分布特征动态调节,但当一个超长请求(如输入长度超过16K token)到达时,其单个请求占用的显存已接近甚至超过批容量的显存预算上限。在这种情况下,无论队列中是否有其他请求,该超长请求都难以与任何请求合批,导致批处理器被迫以批量大小为1的方式执行该请求,吞吐量断崖式下跌。
虚拟批切分策略用于化解这一极端场景。策略的核心是:将超长请求按序列长度切分为多个“虚拟段”,每个虚拟段作为一个独立的微批执行,微批之间共享该请求的上下文状态。例如,将一个32K token的请求切分为4个8K token的微批,每个微批依次执行,KV缓存在微批间持续累积。
微批的执行并非串行等待——当第一个微批在执行时,批处理器可以同时将其他短序列请求插入后续微批的空隙中。这种交错执行模式使超长请求不再独占整个批次,而是与其他请求共享GPU时间,将超长请求对吞吐的负面影响从“独占式”降级为“分摊式”。在测试中,当队列中包含一个32K token的超长请求时,虚拟批切分使整体吞吐量相比单批执行方案提升了约2.3倍。
五、协同设计:批容量调节与显存碎片整理
批容量的频繁调节会改变显存的分配模式,长期运行下可能引发显存碎片化问题——显存中散布着大量无法被有效利用的小块空闲区域,导致有效显存容量减少,进一步压缩批容量的调节空间。
我们在批容量调节器旁部署了一个显存碎片整理模块,在每次批容量更新周期执行一次碎片率检测。碎片率定义为“最大连续空闲块大小/总空闲大小”,当碎片率低于0.3(即最大连续空闲块不足总空闲的30%)时,触发轻度整理——将小尺寸的KV缓存块迁移合并,释放连续大块空间。
碎片整理需要在服务在线状态下执行,且不能影响正在进行的推理。我们采用“整理窗口”策略:仅在批次切换的间隙执行整理操作,每次整理不超过5毫秒,累积整理时长在每个周期内不超过50毫秒。若碎片整理无法在窗口内完成,则分多个周期逐步整理。碎片整理模块上线后,显存有效利用率从82%提升至94%,批容量的实际可调节范围扩大了约20%。
六、实测效果与调优经验
该方案在Token推理服务生产环境中完成部署,覆盖日均约500万次推理请求。测试周期为连续7天,对比基线为固定批容量方案(批大小固定为8)。
在输入长度分布均衡的时段,动态调节方案的吞吐量约为固定方案的103%至108%,略有提升但差异不大。在分布偏斜时段(变异系数>0.6),动态方案的吞吐量提升显著:当变异系数为0.7时,吞吐提升约32%;当变异系数为0.9时,吞吐提升约58%。P99时延方面,动态方案在偏斜分布下较固定方案降低约37%(从420毫秒降至265毫秒),在均衡分布下两者基本持平。
参数调优的两条核心经验:一是双约束模型中计算密度阈值的设置需与GPU型号匹配——高算力GPU(如H系列)的阈值应设得更高,以充分利用计算资源;低算力GPU(如T系列)的阈值应适度降低,避免因过度追求计算密度而导致显存争抢。二是虚拟批切分的段大小需要与页大小对齐(通常为256 token),错位对齐将导致KV缓存的存储效率损失。
结语:输入长度的分布不均是Token推理服务中固有的负载特征,而非异常波动。本文通过动态批容量调节与虚拟批切分的组合策略,将批处理优化从静态配置升级为基于实时分布特征的动态调节,使吞吐量在各类输入分布下均能接近最优状态。核心经验在于:分布感知是调节的前提,双约束模型是调节的依据,虚拟切分是极端场景的保障,碎片整理是长期运行的基石。未来我们将探索将输出长度预测(而非仅输入长度)纳入批容量调节模型,使批处理决策能够兼顾推理过程的动态变化,进一步逼近吞吐与延迟的帕累托最优边界。