单个请求的算子变快,并不意味着同时到达的一组请求都能及时完成。服务系统还必须决定何时接纳请求、哪些请求共同执行、长提示如何穿插,以及资源不足时谁应等待。调度改变的是请求共享资源的方式,其收益与到达过程、长度分布和服务目标有关。
第30章《增量解码》给出可复用状态及其容量,第33章《推理计算优化》给出一次执行的成本。本章将二者放入随时间变化的工作负载中。部署、连接协议与实例生命周期见第32章《模型服务架构》。
31.1请求、时间及容量的计量边界
本章主要符号见表31.1。
表 31.1 批处理调度的主要符号与计量对象。
| 符号 | 含义 |
|---|---|
| \(a_i,b_i,c_i\) | 请求 \(i\) 到达、首次获得执行和终止的时间。 |
| \(u_{i,j}\) | 客户端收到请求 \(i\) 的第 \(j\) 个输出词元的时间。 |
| \(P_i,O_i\) | 输入长度与实际输出长度;\(O_i^{\max}\) 为接纳时约定的输出上限。 |
| \(W_i,T_i,S_i\) | 首次执行前等待时间、系统逗留时间、理想队列模型中的服务时间。 |
| \(N(t),N_q(t)\) | 时刻 \(t\) 系统内和等待队列内的请求数。 |
| \(\lambda,\mu,\rho\) | 队列模型中的到达率、单服务台服务率和利用率。 |
| \(B,K,M\) | 单轮新计算词元预算、活动序列上限和可用缓存字节预算。 |
| \(q_i,s_i,m_i\) | 单轮为请求分配的新位置数、已有上下文长度及缓存字节数。 |
| \(d_i,w_j\) | 请求截止时间与租户 \(j\) 的调度权重。 |
首词元时延(Time to First Token,TTFT)与词元间时延(Inter-Token Latency,ITL)分别为
请求生成至少两个词元时,其平均输出词元时间(Time per Output Token,TPOT)定义为
因此最后一个词元到达的时延恰为 \(\operatorname{TTFT}_i+(O_i-1)\operatorname{TPOT}_i\)。这里的 TTFT 已包含到首次词元之间的排队,不能再次加上 \(W_i=b_i-a_i\)。只有一个词元时 TPOT 不定义;无输出的失败请求必须进入失败统计,不能以零时延代替。
客户端时间还包含网络和缓冲,工作进程内的执行时间不包含这些部分。二者都可记录,但必须说明观测位置。流式协议可能一次传输多个词元;若只能观察数据块,应称为块间隔,而不是把它冒充逐词元 ITL。1
吞吐也有不同口径:请求完成数、输入词元数、输出词元数和满足服务目标的完成数。预填充与解码的计算和搬运成本不同,\(\lambda\mathbb E[P_i+O_i]\) 仅表示词元流量,不能直接视为统一的设备需求。缓存命中又会使输入长度与实际计算长度不同。
31.2连续批处理
静态批处理的容量浪费
静态批处理(Static Batching)在批次开始时确定成员,通常在当前批次退出后才加入下一组请求。已完成序列可以提前返回结果,但空出的执行位置若不能补入新请求,仍会降低资源利用率。不能把静态批处理一概等同于禁止提前返回。
考虑一个仅用于计算的调度模型:所有预填充均已完成,一轮解码固定耗时10毫秒,最多容纳两条序列。三个请求同时到达,剩余输出长度分别为 \(A=4,B=1,C=1\)。静态顺序先选 \(A,B\),\(B\) 在10毫秒完成,\(A\) 在40毫秒完成,\(C\) 在50毫秒完成;平均完成时延为 \(\frac{100}{3}\) 毫秒。若在第二轮将 \(C\) 加入空位,则完成时间变为40、10、20毫秒,平均为 \(\frac{70}{3}\) 毫秒。
连续批处理(Continuous Batching)在迭代边界调整活动成员。Orca 将这种决策落实为迭代级调度,并根据算子特性选择批处理方式(Yu 等 2022)。真实系统的轮时会随批大小、上下文长度和算子形状变化,故图31.1只证明该构造中的收益,不是吞吐预测。
长度分桶及等待窗口
若内核把同批 \(n\) 条序列填充到最大长度 \(P_{\max}\),线性层与显式完整平方注意力矩阵的长度利用率分别为
使用变长分块内核后,不能继续拿这两个比率当作实际计算浪费。
长度分桶(Length Bucketing)把相近长度放入同一执行组,减少形状差异。但等待相近请求会增加时延。动态聚批应同时设置最大等待时间与最大批量:任一条件触发就执行。仅为填满批次持续等待,会在低流量下恶化 TTFT。桶边界附近的长度抖动还可能造成低占用桶,应与第33章《推理计算优化》中的形状分桶中的编译缓存共同设计。
31.3分块预填充及多资源预算
分块预填充的上下文边界
分块预填充(Chunked Prefill)将一个提示的新增位置分多轮处理,每块仍读取合法历史状态;它改变执行时序,不必改变模型可见上下文。SARATHI 研究了预填充分块与解码共同组批的执行方式(Agrawal 等 2023)。具体分块长度须服从设备、批次和服务目标,不能把论文中的某个配置变成普遍最优值。
在已有 \(s_i\) 个位置时处理 \(q_i\) 个新位置,因果注意力所涉及的键查询配对数为
推导是将第 \(r\) 个新查询可见的 \(s_i+r\) 个键对 \(r=1,\ldots,q_i\) 求和。每块重读历史会产生搬运与启动开销;块越小,交互机会越多,但不保证总时间越短。解码通常每序列新增一个位置,预填充则可新增许多位置,因此一个简单预算是
其中 \(\mathcal P_{\rm live}\) 是实际驻留物理页集合,共享前缀只计一次。临时工作区要在可用容量中扣除,不能把设备总显存直接当 KV 预算。
仅限制 \(B\) 仍不够:同样的新词元数在不同 \(s_i\) 下有不同注意力成本。调度器还需使用经测量校准的批次成本估计 \(\widehat t(\{q_i,s_i\})\),在交互目标允许的轮时内选择组合。该函数一般不是各请求独立成本之和,因为共同执行会改变权重重用和有效带宽。
假设与适用范围
以下资源算例假设普通非共享 KV,每词元缓存为64 KiB,页包含16个词元;设备分区已扣除权重与工作区,可用 KV 为64 MiB。实际缓存公式应依据模型层数、键值头数、精度和并行分片确定,不能跨模型复用这个常数。
每页为1 MiB。两条活动序列长度分别为257、255,需 \(17+16=33\) 页。若为它们各解码一步,长度变为258、256,仍为33页。此轮另处理一个新请求的256词元提示块,需要16页,共49页;若该请求声明最终最多使用1024位置,则其完整上界需64页,与已有33页合计97页,不能在64页容量下承诺三者同时完整驻留。
这说明本轮可执行与完整请求可接纳是两个判断。系统可选择保守地预留完整上界,也可动态增长并提供可兑现的抢占、换出或等待策略。不能既按平均输出长度超额接纳,又声称所有请求都有无抢占完成保证。页级管理减少碎片及支持共享,但不创造物理容量(Kwon 等 2023)。
预填充及解码的优先级
始终优先解码可以降低活动请求的词元间隔,却可能使等待提示长期得不到首词元。始终优先新提示又可能使活动输出停顿。可为预填充保留最低服务份额,并在交互轮时预算下分配剩余额度;当多个目标冲突时,应记录超额负载和拒绝,不能用一个平均吞吐数掩盖取舍。
31.4排队关系的推导及适用条件
Little 关系来自驻留面积
Little 关系联系长期平均人数、吞吐与驻留时间(Little 1961)。下面从样本路径面积说明其机制。对观察区间 \([0,H]\),系统内请求数可以写成指示函数之和:
交换有限求和与积分,得到
右侧为每个请求在观察窗内的驻留时间。若系统稳定,长期到达率存在,边界截断对单位时间的贡献趋于零,则除以 \(H\) 并令 \(H\to\infty\),得到
第二式对等待状态重复相同面积论证。LLM 请求可能在多轮之间反复等待,此时 \(W_q\) 应包括所有被统计的等待区间;它与首次执行前的 \(W_i\) 不必相等。
式(31.8)不要求泊松到达或指数服务,但要求人数、吞吐和时间来自同一系统边界与同一请求总体。若将被拒请求计入到达率,却只对接纳请求计算驻留时间,等式失去对应关系。例如稳定系统每秒完成20个请求,平均驻留0.4秒,则平均系统内请求数为8;这不能推出 p99 驻留时间,也不能推出队列必须恰好设置为8。
M/M/1 模型解释高利用率风险
假设与适用范围
设到达为速率 \(\lambda\) 的泊松过程,单服务台独立服务时间服从速率 \(\mu\) 的指数分布,先到先服务、无限等待空间且无放弃,\(\rho=\frac{\lambda}{\mu}<1\)。该模型用于解释机制;连续批处理的服务率随活动集合变化,不直接满足这些条件。
令稳态系统人数概率为 \(\pi_n\)。相邻状态的概率流平衡给出 \(\lambda\pi_n=\mu\pi_{n+1}\),因此 \(\pi_n=\rho^n\pi_0\)。利用几何级数归一化得
结合式(31.8),有
后式从总时间减去平均服务时间 \(\frac{1}{\mu}\) 得到。当 \(\rho\) 接近1,等待呈非线性增长;把设备长期推到饱和不能视为无代价的效率提升。
还可以推导完整逗留时间尾部。独立泊松到达在到达前看到的状态分布为时间稳态分布:直观上,任一短区间发生到达的概率 \(\lambda\,dt\) 不因当时状态改变,因此不会额外偏向某状态。到达看到 \(n\) 个请求时,自身完成需等待 \(n+1\) 个独立指数服务阶段;其中正在服务者的剩余时间利用无记忆性处理。于是对 \(z\ge0\),
这是速率 \(\mu-\lambda\) 的指数分布的拉普拉斯变换,故
若 \(\mu=100\) 请求每秒,\(\lambda=80\),平均逗留50毫秒,p99约230毫秒;到达率升至95时,二者分别为200和921毫秒。这个构造只改变到达率,就产生明显尾部增长。
结论
批处理的请求共享服务轮次,长输出又使驻留长度分布发生变化。不能把上述 \(\mu\) 换成一次离线词元吞吐,就声称获得了真实服务 p99。实际系统应使用按长度、阶段和负载测得的服务曲线,必要时以到达轨迹驱动离散事件模型,并用独立观测校准。
31.5准入、期限及背压
准入控制(Admission Control)发生在承诺接受任务的边界。至少要核查模型与租户配额、请求体与长度上限、缓存增长、队列空间和期限。可以用
作为风险判断,其中 \(\Delta_i\) 为估计误差和协议开销余量。分位数也不能随意相加得到相同分位数的总和;要么直接估计联合总时延,要么使用明确的概率上界。2
背压(Backpressure)把下游容量不足传递给上游。它必须贯穿入口、有界等待队列、活动序列和输出缓冲。如果只限制设备并发,慢客户端仍可能使主机缓冲无限增长。若输出缓冲以每秒 \(r_g\) 字节生成、每秒 \(r_c\) 字节消耗,则积压近似按 \(r_g-r_c\) 增长;当 \(r_g>r_c\),容量 \(H_b\) 的空缓冲将在 \(\frac{H_b}{r_g-r_c}\) 秒后填满。持续消费不足时应暂停、取消或终止,并传播资源释放。
突发到达时,队列吸收的是暂时差额,而不是永久不足。若一段时间内输入速率为 \(\lambda_b\)、有效完成速率为 \(\mu_b<\lambda_b\),持续 \(\tau\) 秒,则新增积压粗估为 \((\lambda_b-\mu_b)\tau\)。这是流体近似,忽略随机波动;必须另外考虑突发形状和请求工作量。扩容有加载延迟时,不能把尚未就绪的设备计入即时服务能力。
31.6公平性及可恢复的抢占
(选修)
公平调度的分配单位
先到先服务(First-Come, First-Served,FCFS)简单且可解释,但长请求可能造成队首阻塞(Head-of-Line Blocking,HOL Blocking)。按最短作业优先在已知独立作业时长等条件下改善平均等待,但输出长度未知,估计误差和长作业饥饿会削弱其适用性。
租户公平可以按请求数、词元数或计算成本定义。每请求一票会偏向长请求,每词元一票又忽略长上下文解码与短上下文解码的成本差异。应选可测量、能核算的成本单位,并公开权重的业务含义。
一种实现是为租户 \(j\) 维护信用额 \(D_j\),每轮增加 \(w_jQ\),执行后减去计费成本 \(c\)。信用不足的候选等待后续轮次;允许有限结转可以容纳较大任务,但应限制无限积累造成的突发。预测成本用于选择,实际成本用于事后纠偏,二者差额不能长期由其他租户承担。共享批次成本难以精确归因,实践中需固定一致的分摊口径,而不能声称存在唯一物理真值。
老化(Aging)随等待增加优先级,可缓解饥饿,但不能在持续超载下保证每个请求都按时完成。截止时间优先也不是无条件最优:本系统同时具有缓存驻留、多资源约束和不可抢占设备片段,不满足许多经典单处理器期限结论的前提。
抢占成本
抢占(Preemption)应发生在安全的迭代边界。已完成输出保持不变,未提交候选与执行状态按明确规则处理。若丢弃缓存,恢复需重算已提交前缀;若换出,则需传输及恢复页映射,并确认模型修订、位置和缓存格式一致。
设重算成本为 \(C_r\),换出和换入共需移动 \(2m\) 字节,有效传输带宽为 \(b\),另有同步成本 \(C_s\)。粗略比较 \(C_r\) 与 \(\frac{2m}{b}+C_s\) 有助于选择,但链路竞争与恢复时设备占用还可能改变结果。频繁抢占会产生反复重算,使观测到的忙碌增加而有效完成减少。应记录重算词元与原始词元的比例,并设置冷却或最小执行份额。
算法31.1 计算过程
单轮有界调度。 输入为等待队列、活动请求、物理页状态、租户信用和本轮预算。
在安全边界处理完成、取消和到期事件,释放引用与预留;已发布终止状态不得重新入队。
增加各租户信用,更新活动解码与等待预填充的期限、年龄和成本估计。
为交互解码与等待预填充分别保留最低服务份额;按权重、期限及年龄选择候选。
对候选确定 \(q_i\),同时检查新词元、序列槽、物理页、工作区和轮时预算。无法容纳时考虑其他可行候选,避免无限队首阻塞。
对本轮计划原子预留页与状态版本。若预留失败,撤销该计划并重新选择,不以部分成功的预留直接执行。
执行一轮;按实际进度提交缓存和输出,按实际计费规则扣减信用,保留尚未完成者。
记录排队、批形状、资源、重算和输出阻塞;若不存在可行计划,等待资源事件或执行明确的拒绝、抢占策略,禁止空转。
31.7尾延迟及有效容量
请求级 TPOT 平均值会掩盖单次长停顿,也会与把所有 ITL 汇总后的均值不同:后者让长输出拥有更大权重。应分别报告请求级分布与词元级分布,并说明权重。输入长度、输出长度、缓存命中、租户和模型修订都可能形成不同的时延切片。
开放环负载(Open-Loop Load)按独立于完成速度的计划提交请求,能够显露过载积压;闭合环负载(Closed-Loop Load)在固定并发用户收到响应后再提交,其到达率会在服务变慢时自行下降。两种模型都可有意义,但回答不同问题。若原目标是固定外部到达流,测试却在每个响应后才继续,就会遗漏拥塞期间本应到达的请求,这种测量偏差常称为协调遗漏(Coordinated Omission)。不能只用闭合环的低尾延迟证明外部突发下的稳定性。
将满足质量与时延目标的成功请求数除以观察时长,可定义该目标下的有效吞吐(Goodput)。例如一个构造性窗口内共提交1000个请求,拒绝100个、失败50个、成功850个,其中700个满足所有目标,窗口100秒,则提交率10、成功吞吐8.5、有效吞吐7请求每秒。若只在成功者中报告满足率,得到 \(\frac{700}{850}\);若从所有提交者看,则是70%。二者必须注明分母。
调度策略比较应保持模型、生成参数、输入轨迹与输出预算一致;随机生成导致工作量不同,应多次重复或使用可解释的受控长度实验。报告原始到达计划、被接纳请求、失败与取消,不把超时样本删除后再计算漂亮的 p99。质量变化带来的短输出也不能冒充纯调度加速。