当前位置: 首页 > news >正文

大模型推理服务的批处理与动态 Batch 调度:从逐条推理到吞吐量优化

大模型推理服务的批处理与动态 Batch 调度:从逐条推理到吞吐量优化

一、推理服务的吞吐量瓶颈:GPU 利用率的隐性浪费

大模型推理服务的核心瓶颈不是单次请求的延迟,而是 GPU 利用率。在逐条推理模式下,每个请求独立送入 GPU 计算,Batch Size 为 1,GPU 的并行计算能力大量闲置。以 A100 GPU 为例,Batch Size 1 时 GPU 利用率通常不足 20%,而 Batch Size 8-16 时可提升至 70% 以上。

批处理(Batching)是提升推理吞吐量的关键手段:将多个请求合并为一个 Batch 送入 GPU,利用矩阵运算的并行性摊薄计算开销。但批处理的引入带来新的挑战:请求到达时间不同,需要等待凑批,增加了尾延迟;Batch 内请求的序列长度差异导致 Padding 浪费;动态流量下 Batch Size 的最优值持续变化。动态 Batch 调度系统需要在吞吐量与延迟之间找到动态平衡点。

二、动态 Batch 调度的核心机制

flowchart TD A[请求到达] --> B[请求队列] B --> C[Batch 调度器] C --> D{调度策略} D -->|时间窗口到期| E[组装当前队列所有请求] D -->|队列长度达到上限| F[组装最大 Batch] D -->|最长等待超时| G[立即发送已有请求] E --> H[Padding 与注意力掩码] F --> H G --> H H --> I[GPU 推理] I --> J[结果拆分与返回] subgraph 连续批处理 Continuous Batching K[迭代级调度] K --> L[每步重新评估 Batch] L --> M[已完成序列让出位置] M --> N[新请求填入空位] end C --> K

静态批处理(Static Batching)在凑满 Batch 后一次性推理,Batch 内所有序列必须等待最长序列完成才能返回。连续批处理(Continuous Batching)在每次迭代(生成一个 Token)后重新评估 Batch:已完成的序列立即让出位置,新请求填入空位,显著降低平均等待时间。

三、工程实现:基于 vLLM 的动态 Batch 推理服务

# dynamic_batch_server.py — 动态 Batch 推理服务 from fastapi import FastAPI from pydantic import BaseModel import asyncio import time from typing import List, Optional from vllm import LLM, SamplingParams from vllm.entrypoints.openai.api_server import init_app app = FastAPI() class InferenceRequest(BaseModel): prompt: str max_tokens: int = 256 temperature: float = 0.7 top_p: float = 0.9 priority: int = 0 # 0=普通, 1=高优先级 class InferenceResponse(BaseModel): text: str tokens: int latency_ms: float # vLLM 引擎初始化:启用 Continuous Batching llm = LLM( model="Qwen/Qwen2.5-72B-Instruct", tensor_parallel_size=2, # 2 卡并行 max_num_seqs=64, # 最大并发序列数 max_num_batched_tokens=32768, # 单 Batch 最大 Token 数 gpu_memory_utilization=0.90, # GPU 显存利用率上限 enable_prefix_caching=True, # 启用前缀缓存,复用 System Prompt ) # 推理端点:vLLM 内部自动管理 Batch 调度 @app.post("/v1/completions", response_model=InferenceResponse) async def completions(request: InferenceRequest): start_time = time.monotonic() sampling_params = SamplingParams( max_tokens=request.max_tokens, temperature=request.temperature, top_p=request.top_p, ) # vLLM 的 add_request 自动进入 Continuous Batching 队列 outputs = llm.generate( prompts=[request.prompt], sampling_params=sampling_params, use_tqdm=False, ) latency_ms = (time.monotonic() - start_time) * 1000 output = outputs[0] return InferenceResponse( text=output.outputs[0].text, tokens=len(output.outputs[0].token_ids), latency_ms=latency_ms, )
# batch_metrics.py — Batch 调度指标监控 from prometheus_client import Histogram, Gauge, Counter import time from functools import wraps # 核心指标定义 BATCH_SIZE = Histogram( 'inference_batch_size', 'Batch 大小分布', buckets=[1, 2, 4, 8, 16, 32, 64] ) QUEUE_LENGTH = Gauge( 'inference_queue_length', '等待队列中的请求数' ) INFERENCE_LATENCY = Histogram( 'inference_latency_ms', '推理延迟分布', buckets=[50, 100, 200, 500, 1000, 2000, 5000] ) GPU_UTILIZATION = Gauge( 'gpu_utilization_percent', 'GPU 利用率' ) TOKENS_PER_SECOND = Gauge( 'inference_tokens_per_second', '每秒生成 Token 数' ) def track_batch_metrics(func): @wraps(func) async def wrapper(*args, **kwargs): # 记录队列长度 QUEUE_LENGTH.set(get_current_queue_length()) start = time.monotonic() result = await func(*args, **kwargs) latency = (time.monotonic() - start) * 1000 INFERENCE_LATENCY.observe(latency) return result return wrapper # 动态 Batch Size 调优:基于延迟 SLO 调整最大 Batch class AdaptiveBatchController: def __init__(self, latency_slo_ms: float = 500): self.latency_slo_ms = latency_slo_ms self.max_batch_size = 16 self.min_batch_size = 1 def adjust(self, current_p99_latency: float): """根据 P99 延迟动态调整最大 Batch Size""" if current_p99_latency > self.latency_slo_ms * 1.5: # 延迟超标,减小 Batch Size self.max_batch_size = max( self.min_batch_size, self.max_batch_size - 2 ) elif current_p99_latency < self.latency_slo_ms * 0.5: # 延迟充裕,增大 Batch Size 提升吞吐 self.max_batch_size = min(64, self.max_batch_size + 2)

四、动态 Batch 调度的边界与权衡

Padding 浪费:Batch 内不同序列长度差异导致短序列需要 Padding 到最长序列的长度,浪费计算资源。vLLM 的 PagedAttention 通过虚拟内存管理减少 Padding 浪费,但极端长度差异(1:10 以上)仍会显著影响有效吞吐。建议对请求按长度分桶,相似长度的请求组成同一 Batch。

凑批延迟:等待凑批的时间增加了请求的尾延迟。在低流量时段,凑批等待可能成为延迟的主要来源。解决方案是设置最大等待时间(如 50ms),超时后即使 Batch 未满也立即发送,避免无限等待。

KV Cache 显存竞争:Batch 内所有序列的 KV Cache 共享 GPU 显存,长序列消耗大量显存,可能挤占其他序列的空间。vLLM 的 PagedAttention 按需分配 KV Cache 页,但显存不足时仍需拒绝新请求。需根据模型大小与 GPU 显存合理设置max_num_seqs

流式输出的兼容性:Continuous Batching 与流式输出(SSE)存在天然矛盾:流式要求 Token 级别的即时返回,而 Batching 需要等待整个迭代步完成。vLLM 通过迭代级调度解决了这一问题——每个 Token 生成后立即返回,同时维护 Batch 状态。

五、总结

动态 Batch 调度是大模型推理服务吞吐量优化的核心手段。Continuous Batching 通过迭代级调度实现"完成即让位",显著降低平均等待时间。工程落地的关键在于:PagedAttention 减少 Padding 浪费、自适应 Batch Size 控制器基于延迟 SLO 动态调优、最大等待时间避免凑批延迟、按长度分桶优化 Batch 内序列长度一致性。推理服务的优化不是单一维度的调参,而是在吞吐量、延迟与显存利用率三个目标间的持续权衡。

http://www.zskr.cn/news/1514587.html

相关文章:

  • 慢慢来,坚持走更远
  • DistroAV网络视频传输终极指南:告别复杂布线,开启多设备无线直播新时代
  • 2026年小区换热站怎么选?五大供应商多维评测与实战案例解析 - 优质品牌商家
  • ArduPilot飞控GPS模块选型与配置实战:从NMEA到RTK,手把手教你避开那些坑
  • 别再瞎调XGBoost了!用Optuna搞定这10个核心参数,Kaggle老手都这么干
  • 2026年 东莞吸塑内托/广东内嵌吸塑内托/环保吸塑内托厂家推荐排行榜:精密成型与绿色包装实力之选 - 品牌发掘
  • 深度学习正则化策略:从 Dropout 到 DropPath,训练稳定性与泛化能力的工程保障
  • AI 与诗词生成:从语言模型到意境表达,当算法遇见古典文学的跨界实验
  • 抛弃纯AI自研:制造业转型认准AI+低代码底层逻辑
  • GAN数据增强在ALICE重离子碰撞实验中的应用与优化
  • 别再死记硬背了!用Python列表玩转‘摩尔斯电码’和‘个人数据脱敏’两个趣味项目
  • Java SSM酒店预订系统源码包:含前台订房+后台管理+MySQL数据库
  • 揭秘智能解析架构:如何将百度网盘资源获取效率提升10倍
  • 3步解锁QQ音乐加密文件:macOS用户必备的格式转换终极方案
  • AI 生成数学公式复制到 Word/WPS 后乱码怎么办?从 LaTeX 到可编辑公式 - 【DS随心转】
  • 工商业分布式光伏箱变智能监控落地实战
  • 高寒风沙环境下风电箱变长效稳定运行实战
  • 在上海挑ECO棉床垫,我跑了几家店后总算心里有数了 - 深圳市民HLL
  • 2026年6月成都机麻短租热门公司联系方式与选型指南 - 品牌鉴赏官2026
  • 2026 HR 新趋势:AI 加速人力资源战略转型
  • 手机租赁业务全局代理 PAC 配置实战指南
  • ROS Noetic下,手把手教你为URDF机器人模型添加深度摄像头(Gazebo仿真)
  • 2026年北京刑事辩护律师怎么挑?5个关键判断标准防踩雷 - 本地品牌推荐
  • Stata面板数据回归前必做:6种单位根检验保姆级实操指南(附完整代码与结果解读)
  • MSP430G2553入门实战:从按键消抖到串口调试,一个完整项目带你玩转GPIO与中断
  • 2026年出国打工怎么找正规劳务公司?行业深度分析与真实案例参考 - 优质品牌商家
  • 告别命令行恐惧!用TortoiseGit(小乌龟)和Gitee搞定团队协作,组长和组员都能看懂的保姆级配置
  • 2026年更新:长沙可靠的品牌活动策划服务公司盘点与青柚传媒深度解析 - 品牌鉴赏官2026
  • FMS 文件管理系统(开源私有文件云盘系统)-支持WebDAV协议以及存储镜像管理-可软替代NAS
  • 如何用vmulti构建Windows虚拟HID设备:从零到实战的5个核心挑战与解决方案