news 2026/2/9 10:53:15

批处理策略:Dynamic Batching在并发场景下的实现逻辑

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
批处理策略:Dynamic Batching在并发场景下的实现逻辑

在高性能大模型推理系统中,批处理(Batching)是提升吞吐量(Throughput)最有效的手段。然而,LLM(Large Language Model)推理场景的特殊性——输入Prompt长度不一、输出Token数量不可预测,使得传统的批处理策略显得捉襟见肘。

本文将深入剖析DeepSeek推理服务中的核心优化技术:Dynamic Batching(动态批处理),亦称为Continuous Batching(连续批处理),并探讨其在昇腾NPU环境下的实现细节。

1. 传统困境:Static Batching的效率黑洞

在传统的深度学习推理(如ResNet图像分类)中,Batching非常简单:凑够N张图,打包成一个Tensor,送入GPU计算。这种策略被称为Static Batching(静态批处理)

但在LLM场景下,Static Batching面临两个致命问题:

1.1 Padding带来的算力浪费

假设我们设定Batch Size = 4,但这4个请求的输入长度分别是[10, 20, 100, 50]。为了构建一个规则的Tensor矩阵(Shape:[4, 100]),必须将短序列用Pad Token(通常是0)填充至最长序列的长度(100)。

这意味着:

  • 请求1(长度10):有90%的计算量是在算无效的Pad。
  • 请求2(长度20):有80%的计算量是无效的。

在极端情况下,如果混入了一个超长Prompt,整个Batch的推理延迟将被这个“长尾”请求拖垮,且大部分算力都在做无用功。

1.2 “队头阻塞”问题

LLM是自回归生成模型,生成长度是未知的。

  • 请求A生成了10个Token就结束了(<EOS>)。
  • 请求B生成了500个Token还在继续。

在Static Batching模式下,必须等待请求B完全生成结束,请求A才能返回给用户。这导致请求A的用户感知延迟(Latency)极高,体验极差。这就像坐公交车,全车人必须等最后一名乘客下车才能发车。

2. 破局之道:Continuous Batching (Orca机制)

2023年,OSDI发表了一篇里程碑式的论文Orca: A Distributed Serving System for Transformer-Based Generative Models,提出了Iteration-level Scheduling(迭代级调度)的概念,彻底改变了LLM推理的游戏规则。

2.1 核心理念:不等车,随到随走

Continuous Batching 将调度的粒度从“请求级”下沉到了“迭代级”(Token级)。系统不再维护一个固定的Batch,而是维护一个动态的请求池

每一次生成Token的迭代(Step),系统都会检查当前状态:

  1. 清理(Evict):检查哪些请求生成了<EOS>结束符。如果有,立即释放其占用的显存槽位。
  2. 填充(Fill):如果当前Batch内的请求数未达到上限(Max Batch Size),或者Token总数未达到显存瓶颈,就从等待队列(Waiting Queue)中拉取一个新的请求插入。
  3. 合并(Merge):将新加入请求的Prefill(首字生成)阶段与现有请求的Decode(后续生成)阶段合并,组成一个新的Batch进行一次前向计算。

这种机制下,显卡几乎永远处于满载状态,且没有Padding浪费。短请求处理完立即返回,长请求继续生成,互不干扰。

2.2 显存管理的基石:PagedAttention

Dynamic Batching的高效运作离不开显存管理的革新。由于请求是随机进出的,如果使用连续内存存储KV Cache,必然导致严重的内存碎片化

PagedAttention(vLLM的核心技术)借鉴了操作系统虚拟内存的分页思想:

  • 将KV Cache切分成固定大小的Block(例如每块存储16个Token)。
  • 在显存中维护一个Block Table,记录逻辑Block到物理Block的映射。
  • 生成的Token可以存储在显存的任意位置,不再要求物理连续。

这就好比操作系统管理内存,无论进程申请多少内存,底层都是由离散的Page组成的。这使得显存利用率接近100%,从而支持更大的Batch Size。

3. 在昇腾上实现Dynamic Batching

在昇腾CANN架构上,我们通常通过MindIE (MindSpore Inference Engine)来启用这一特性,或者在PyTorch层结合Ascend Speed实现。

3.1 方案一:MindIE原生配置(推荐)

MindIE Service是华为官方推出的推理服务框架,底层已经深度集成了Continuous Batching和PagedAttention。

只需在config.json中进行简单配置:

{"scheduler":{"type":"continuous_batching","max_batch_size":128,// 最大并发请求数"max_input_len":4096,// 最大输入长度"max_output_len":2048,// 最大输出长度"max_waiting_queue":2000// 等待队列长度},"model":{"block_size":16,// PagedAttention的块大小"max_prefill_tokens":8192// 限制单次迭代处理的最大Token数,防止OOM}}

关键参数调优建议

  • block_size:通常设为16或32。太小会导致Block Table过大,太大会导致块内碎片(Internal Fragmentation)。
  • max_prefill_tokens:非常关键。如果新进来的Prompt很长,为了避免Prefill阶段耗时过长导致Decode阶段卡顿(抖动),可以限制单次Prefill的Token数,启用Chunked Prefill(分块预填充)。

3.2 方案二:Python自定义调度(灵活性高)

如果你需要更复杂的调度策略(例如基于优先级的VIP通道),可以在Python层实现一个简易调度器。以下是一个简化版的实现逻辑:

classContinuousBatchScheduler:def__init__(self,model,max_bs=32):self.active_reqs=[]# 正在生成的请求self.waiting_queue=deque()# 等待队列self.model=model self.max_bs=max_bsdefstep(self):# 1. 移除已完成的请求(EOS或达到最大长度)# 这一步需要收集上一次推理的输出,判断stop_reasonfinished_ids=[req.idforreqinself.active_reqsifreq.is_finished()]self.active_reqs=[reqforreqinself.active_reqsifnotreq.is_finished()]# 释放显存Block(伪代码)self.block_manager.free(finished_ids)# 2. 动态填充新请求# 策略:在显存允许且Batch未满的情况下,尽可能多地加入新请求whilelen(self.active_reqs)<self.max_bsandself.waiting_queue:# 预估加入该请求后是否会OOMcandidate_req=self.waiting_queue[0]ifnotself.block_manager.can_allocate(candidate_req):breaknew_req=self.waiting_queue.popleft()self.active_reqs.append(new_req)self.block_manager.allocate(new_req)# 3. 构造Batch输入# 这一步极其复杂,需要处理Ragged Tensor(不规则张量)# 通常配合Flash Attention的varlen接口,传入cu_seqlensinputs,cu_seqlens,position_ids=self.prepare_inputs(self.active_reqs)# 4. 执行推理logits=self.model(inputs,position_ids)# 5. 更新请求状态self.update_requests(self.active_reqs,logits)defprepare_inputs(self,reqs):# 将所有请求的Token拼接成一个长的一维Tensorinput_ids=torch.cat([req.tokensforreqinreqs])# 计算累积长度,供Flash Attention使用seqlens=[len(req.tokens)forreqinreqs]cu_seqlens=torch.tensor([0]+list(accumulate(seqlens)),dtype=torch.int32)returninput_ids,cu_seqlens

4. 挑战与权衡

虽然Dynamic Batching是提升吞吐量的神器,但在实际落地中也面临挑战:

4.1 调度开销(Scheduling Overhead)

在每一轮生成Token之间,都要运行一次Python调度逻辑(移除、添加、构造Tensor)。如果Python代码运行太慢(例如超过5ms),而NPU生成一个Token只需要10ms,那么调度开销就占了33%,严重拖慢整体速度。

  • 优化策略:使用C++重写调度器(如vLLM的做法),或者使用CUDAGraph/AscendGraph固化计算图。

4.2 显存碎片化与Swap

虽然PagedAttention解决了碎片化,但当负载极高时,显存仍然可能耗尽。此时需要将部分KV Cache从NPU显存Swap Out到CPU内存,等有空位了再Swap In。这涉及复杂的内存分级存储管理。

4.3 精度对齐

由于Dynamic Batching使用了Flash Attention的变长接口和自定义的位置编码,验证其与HuggingFace原生实现的精度对齐(Perplexity一致性)是一个繁琐但必须的过程。

5. 总结

Dynamic Batching 实际上是将时间维度的不确定性(生成长度)转化为空间维度的确定性(显存填满)。在DeepSeek的高并发服务中,开启Dynamic Batching通常能带来2-4倍的吞吐量提升,是构建生产级推理服务不可或缺的基石。对于昇腾开发者而言,优先使用MindIE是最高效的路径,但在特殊场景下,理解其背后的调度原理对于深度调优至关重要。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/5 15:08:53

YOLO11镜像实测:训练效果超出预期

YOLO11镜像实测&#xff1a;训练效果超出预期 你是不是也经历过——花三天配环境&#xff0c;结果卡在conda create报权限错误&#xff1b;查了二十篇博客&#xff0c;发现每篇的CUDA版本要求都写得模棱两可&#xff1b;好不容易跑通训练&#xff0c;验证指标却比预期低一截&a…

作者头像 李华
网站建设 2026/2/6 16:43:12

5分钟部署YOLOE官版镜像,零基础实现开放词汇目标检测

5分钟部署YOLOE官版镜像&#xff0c;零基础实现开放词汇目标检测 你是否试过在一张图里找“消防栓”“无人机”“复古台灯”&#xff0c;却被告知模型只认识COCO数据集里的80个类别&#xff1f;是否为新增一个检测目标&#xff0c;就得重新标注几百张图、训练一整天&#xff1…

作者头像 李华
网站建设 2026/2/5 21:21:48

语音合成API计费系统:基于Sambert的调用次数统计实现

语音合成API计费系统&#xff1a;基于Sambert的调用次数统计实现 1. 开箱即用的多情感中文语音合成体验 你有没有遇到过这样的场景&#xff1a;刚部署好一个语音合成服务&#xff0c;还没来得及测试效果&#xff0c;就发现调用量已经超限&#xff1f;或者团队多人共用一个API…

作者头像 李华
网站建设 2026/2/7 19:49:11

Qwen3-Embedding-4B成本优化:小显存GPU部署实战案例

Qwen3-Embedding-4B成本优化&#xff1a;小显存GPU部署实战案例 在实际业务中&#xff0c;向量检索已成为搜索、推荐、RAG等系统的基础设施。但很多团队卡在第一步&#xff1a;如何用有限资源跑起高质量嵌入模型&#xff1f;尤其是当显存只有12GB甚至8GB的A10、RTX 4090或L4时…

作者头像 李华
网站建设 2026/2/9 0:02:54

YOLOv9实战案例:零售货架商品识别系统搭建步骤

YOLOv9实战案例&#xff1a;零售货架商品识别系统搭建步骤 在零售行业&#xff0c;自动化的商品识别正成为提升运营效率的关键技术。传统的人工盘点耗时耗力&#xff0c;而基于AI的视觉识别方案可以实现快速、准确的商品检测与统计。本文将带你使用 YOLOv9 官方版训练与推理镜…

作者头像 李华
网站建设 2026/2/7 7:04:18

《Nature》子刊:没苦硬吃不可取!

人们常说“吃得苦中苦&#xff0c;方为人上人”&#xff0c;但事实真的如此吗&#xff1f;2024年4月&#xff0c;来自德国柏林夏里特医学院的科研团队在Nature子刊《Molecular Psychiatry》上发表了一篇重磅综述&#xff0c;题为“The impact of psychosocial adversity on bra…

作者头像 李华