模型服务化中的请求调度策略:FIFO、批处理与优先级队列对比

📅 2026/7/9 18:30:17
模型服务化中的请求调度策略:FIFO、批处理与优先级队列对比
模型服务化中的请求调度策略FIFO、批处理与优先级队列对比一、模型推理调度是一个排队论问题而非简单的先到先服务当模型训练完毕部署为在线服务后核心问题从如何最大化训练吞吐转变为如何在延迟约束下最大化资源利用率。这个转变将调度问题推入了排队论的框架——你的服务是一个队列系统请求是到达的顾客GPU是服务员你需要决定服务顺序和批次组合。三种基本调度策略——FIFO先到先服务、Dynamic Batching动态批处理、Priority Queue优先级队列——各有自己的延迟-吞吐特性曲线。选择不当可能导致一种令人困惑的现象GPU利用率很高80%但P99延迟也很高500ms用户体验却很差。flowchart TB subgraph FIFO[FIFO: 先到先服务] F1[请求到达] -- F2[排队] F2 -- F3[按到达顺序逐个处理] F3 -- F4[低GPU利用率, 延迟可预测] end subgraph DB[Dynamic Batching: 动态批处理] D1[请求到达] -- D2[等待窗口] D2 -- D3{凑够batch或超时?} D3 --|凑够| D4[批量推理] D3 --|超时| D5[以当前batch推理] D4 -- D6[高吞吐, P99受超时控制] D5 -- D6 end subgraph PQ[Priority Queue: 优先级队列] P1[请求到达] -- P2{优先级分级} P2 --|高优: 在线用户| P3[优先队列头部] P2 --|低优: 离线批处理| P4[低优先级等待] P3 -- P5[低延迟保障, 但可能饿死低优任务] end二、动态批处理的等待时间与实际延迟的数学关系动态批处理的核心参数是max_batch_size和max_queue_delay。两者之间的关系可以通过排队论建模设请求到达率为 λrequests/second单样本推理时间为 t_inf则平均batch形成时间 1/λ×max_batch_size如果 λ 足够高如果1/λ × max_batch_size max_queue_delay则实际batch max_batch_size请求密度不够P99排队延迟 ≈max_queue_delay当请求密度低时大多数请求需要等待完整的delay周期这个模型揭示了一个关键洞察max_queue_delay 不仅是一个最大等待时间的承诺也是P99延迟的主要贡献项。如果将 delay 设为 100msP99 延迟将至少为 100ms 推理时间。import heapq import time from typing import List, Dict, Optional, Callable from dataclasses import dataclass, field from enum import Enum import numpy as np class Priority(Enum): HIGH 0 # 实时用户请求 NORMAL 1 # 批量分析请求 LOW 2 # 离线任务 dataclass(orderTrue) class InferenceRequest: 带优先级的推理请求。 使用 dataclass 的 orderTrue 自动生成比较方法 heapq 可以直接用于优先级排序。 比较优先级: priority → arrival_time priority: Priority arrival_time: float input_data: Dict field(compareFalse) request_id: str field(compareFalse) class PriorityBatchScheduler: 优先级批量调度器。 设计决策 1. 高优请求不等待到达后立即触发推理batch_size可能为1 2. 普通请求等待 max_delay 凑batch 3. 低优请求仅在 GPU 空闲时处理 为什么不让高优请求也等待batch 高优请求通常是交互式的如聊天用户期望毫秒级响应。 让用户等100ms凑batch会显著影响体验。 这个取舍是必要的——高优请求的延迟优先级高于吞吐优化。 def __init__( self, max_batch_size: int 32, max_queue_delay_ms: float 50.0, inference_fn: Optional[Callable] None ): self.max_batch_size max_batch_size self.max_queue_delay max_queue_delay_ms / 1000.0 # 转为秒 self.inference_fn inference_fn # 三个优先级队列heapq 最小堆优先级值小的先出 self.queues { Priority.HIGH: [], Priority.NORMAL: [], Priority.LOW: [] } # 统计 self.stats { total_processed: 0, avg_batch_size: 0.0, latencies: [] } def submit(self, request: InferenceRequest): 提交推理请求到对应优先级队列。 heapq.heappush(self.queues[request.priority], request) def _collect_batch(self) - List[InferenceRequest]: 收集一批请求优先处理高优先级。 收集策略 1. 先检查高优队列——如果有不等待立即返回 2. 如果没有高优从普通队列收集最多等待 max_delay 3. 如果都没有从低优队列收集 batch [] # 高优请求不等待 if self.queues[Priority.HIGH]: while self.queues[Priority.HIGH] and len(batch) self.max_batch_size: batch.append(heapq.heappop(self.queues[Priority.HIGH])) return batch # 普通请求等待 max_delay 凑batch if self.queues[Priority.NORMAL]: oldest_arrival self.queues[Priority.NORMAL][0].arrival_time wait_time time.time() - oldest_arrival if wait_time self.max_queue_delay or len(self.queues[Priority.NORMAL]) self.max_batch_size: while self.queues[Priority.NORMAL] and len(batch) self.max_batch_size: batch.append(heapq.heappop(self.queues[Priority.NORMAL])) return batch # 等待时间还不够返回空batch让调用者知道暂无请求需要处理 return [] # 低优请求尽量凑大batch if self.queues[Priority.LOW]: while self.queues[Priority.LOW] and len(batch) self.max_batch_size: batch.append(heapq.heappop(self.queues[Priority.LOW])) return batch def get_queue_depth(self) - Dict[Priority, int]: 返回各优先级队列的深度用于监控。 return {p: len(q) for p, q in self.queues.items()}三、尾部延迟的来源分析与缓解策略模型推理服务中P99延迟远高于P50延迟的长尾现象主要有三个来源排队抖动请求到达模式的突发性导致某些请求等待时间远超平均。如果请求以泊松过程到达λ10 QPS偶尔会有50请求在100ms窗口内到达导致队列瞬时积压。可变推理时间对于自回归生成模型生成长度不同导致推理时间不同。一个生成100个token的请求耗时是生成10个token的10倍——如果它们在同一batch中短请求会被长请求拖慢。GPU Kernel启动开销抖动在大batch下GPU的kernel启动和调度开销会增加。尤其是当batch中包含不同形状的输入时需要padding到统一长度padding开销会放大尾部延迟。缓解策略对生成长度设置硬上限截断过长的请求、使用分离的短/长请求队列、预热GPU kernel发送dummy数据保持GPU处于高频状态。四、调度策略选择的决策框架场景推荐策略原因在线聊天API (P99 200ms)FIFO 小batch可预测的低延迟优于高吞吐批量文档处理Dynamic Batching吞吐优先延迟不敏感混合场景(在线离线)Priority Queue在保障SLA的前提下利用闲置算力图像/视频分析 (固定推理时间)Dynamic Batching推理时间稳定batch预测准确五、总结模型推理调度是延迟 vs 吞吐权衡的工程体现FIFO 提供最低且最可预测的延迟代价是GPU利用率低。Dynamic Batching 最大化吞吐代价是引入排队延迟受max_queue_delay控制。Priority Queue 在混合负载场景中提供延迟和资源利用的差异化保障。调度策略的选择应基于业务的延迟SLA和负载特征没有绝对正确的方案。