Dynamic Batching(動態批處理)
3 秒看懂
一句話:讓 GPU 在推論時”來多少算多少、攢夠就跑”,而不是傻等固定數量的請求到齊——把延遲和吞吐之間的矛盾,用動態拼批的策略化解掉。
一句話判斷:Dynamic Batching 是 LLM 推論服務端最核心的系統級最佳化之一,直接影響 GPU 利用率和推論成本,是 vLLM、TensorRT-LLM、Triton 等推論引擎的關鍵差異點。
3 分鐘產業解釋
為什麼需要它?
想像一家餐廳的後廚:
- 沒有 Dynamic Batching(靜態批處理):廚師要等滿 8 個一模一樣的菜名才開始做,哪怕前面已經來了 6 個”番茄炒蛋”,也必須再等 2 個,同時對所有菜品用同一時間出鍋——誰先做完都得等最慢的那道。
- 有了 Dynamic Batching:廚師看到 6 個”番茄炒蛋”,夠一鍋了就先炒;中間又來 3 個”麻婆豆腐”,又夠一鍋了就做;先做完的先出,不用等。
產業意義
在 LLM 推論場景下,每個請求的輸入/輸出長度差異巨大(從幾十 token 到數千 token)。如果用靜態批處理:
- 短請求被長請求”綁架”:短請求早就生成完了,但必須等同批最長的請求完成才能返回。
- GPU 算力浪費嚴重:批內已結束的請求佔用視訊記憶體和計算資源卻不產出。
- 成本居高不下:同樣的 GPU 叢集,吞吐可能只有 Dynamic Batching 方案的幾分之一。
Dynamic Batching 直接把推論服務的吞吐/成本效率拉昇一個量級,是推論側降本的核心手段之一。
15 分鐘專家深入
核心機制分層
Dynamic Batching 在實踐中逐步演化出三個層次:
| 層次 | 名稱 | 核心思想 | 代表系統 |
|---|---|---|---|
| L1 | 請求級動態批處理 (Request-level) | 在一個時間視窗內把到達的請求拼成一個 batch,統一送入 GPU | NVIDIA Triton Dynamic Batching |
| L2 | 連續批處理 / 迭代級排程 (Continuous / Iteration-level Batching) | 在 decoding 的每個 step 級別排程:已完成的請求退出、新請求加入,batch 組成動態變化 | Orca (OSDI’22)、vLLM、TensorRT-LLM (In-flight Batching) |
| L3 | Prefill-Decode 分離排程 (Disaggregated Scheduling) | 把計算密集的 prefill 階段和訪存密集的 decode 階段拆到不同 GPU/例項上,各自獨立做 dynamic batching | Splitwise (ISCA’24)、DistServe 等研究原型 |
關鍵技術細節
1. 為什麼 L1 不夠?——“bubble” 問題
在請求級批處理中,一旦一個 batch 啟動,批內所有序列必須走完所有 decoding step。短序列早早 EOS 但仍然佔用 GPU 資源(視訊記憶體中的 KV cache、執行緒束中的計算),造成 bubble(氣泡),即無效計算。
時間 →
┌──────────────────────────────────────────┐
│ Request A (短): ████████░░░░░░░░░░░░░░░░ │ ← 已完成,但被迫等待
│ Request B (中): ████████████████████░░░░░ │ ← 還在跑
│ Request C (長): █████████████████████████ │ ← 最慢
└──────────────────────────────────────────┘
░░░ = bubble(浪費的 GPU 資源)
2. Continuous Batching 如何消除 bubble?
以 Orca 提出的 iteration-level scheduling 為例:
Step 1: [A, B, C] 一起 decode
Step 2: [A, B, C] 一起 decode
Step 3: [A 完成, 退出] → [B, C, D(新到)] 一起 decode ← A 的槽位立刻被 D 佔用
Step 4: [B, C, D] 一起 decode
...
關鍵機制:
- 迭代級排程器(Iteration-level Scheduler):每個 decoding step 之前重新決定 batch 內容。
- 請求退出/加入:已生成 EOS token 的請求立即退出,釋放 KV cache;佇列中等待的新請求立即補入空位。
- 避免 padding:不同請求解碼不同數量的 token,排程器逐請求追蹤狀態,不再需要對齊到最長序列。
3. Prefill-Decode 分離與異構批處理
最新的研究觀察到:
- Prefill 階段:計算密集(大量矩陣乘法處理 prompt),算術強度高,適合用計算頻寬大的 GPU。
- Decode 階段:訪存密集(逐 token 生成,每步只計算一層的啟用,但需要載入全部模型權重),瓶頸在視訊記憶體頻寬,需要高 HBM 頻寬。
兩者混合在同一 GPU 上會導致:
- Prefill 請求的長計算阻塞 Decode 請求的低延遲需求。
- Decode 請求的低算術強度拉低 GPU 計算利用率。
分離後各自做獨立的 Dynamic Batching:
- Prefill 例項做請求級動態拼批(按 prompt 長度和 max batch size 聚合)。
- Decode 例項做連續批處理(高頻迭代排程)。
技術原理
一、傳統靜態批處理 vs 動態批處理
========== 靜態批處理 (Static Batching) ==========
請求佇列: [Req1, Req2, Req3, ...]
│
▼
┌─────────────────┐
│ 等待 batch 滿 │ ← 固定 batch_size = N,必須攢滿
│ 或超時觸發 │
└─────────────────┘
│
▼
┌─────────────────┐
│ Pad 到統一長度 │ ← 短序列用 padding 填齊
│ 統一送入 GPU │
└─────────────────┘
│
▼
┌─────────────────┐
│ 全部生成完成 │ ← 最慢的請求決定整體延遲
│ 統一返回 │
└─────────────────┘
二、動態批處理的核心排程邏輯
========== Dynamic Batching (請求級) ==========
while True:
1. 收集 [0, max_wait_time] 視窗內到達的所有請求
2. 按以下約束拼批:
- 總 token 數 ≤ max_tokens_in_batch ← 關鍵:按 token 預算而非請求數
- 請求數 ≤ max_batch_size
- 滿足 SLO 的延遲約束
3. 對齊 padding(僅在 batch 內部對齊)並送入 GPU
4. 處理完成後立即返回該批次結果
5. 回到步驟 1
三、連續批處理(Continuous Batching)的排程狀態機
========== Iteration-level Scheduling ==========
Global State:
active_batch = [] # 當前正在 decode 的請求集合
waiting_queue = FIFO() # 等待進入的請求
Per Decode Step:
┌──────────────────────────────────────────┐
│ 1. Check active_batch 中每個請求: │
│ - 若 generated EOS 或 max_len → 退出 │
│ - 否則 → 留在 batch │
│ │
│ 2. 計算空閒槽位數 = max_batch │
│ - len(active_batch) │
│ │
│ 3. 從 waiting_queue 取出 ≤ 空閒槽位數 │
│ 的新請求,執行 prefill,加入 batch │
│ │
│ 4. 對 active_batch 執行一步 decode │
└──────────────────────────────────────────┘
四、關鍵引數與約束
| 引數 | 含義 | 典型取值範圍(估算) |
|---|---|---|
max_batch_size | 一個 decode step 中同時處理的最大請求數 | 取決於 GPU 視訊記憶體,7B 模型在 A100-80G 上可支援數百(估算) |
max_tokens_in_batch | 一個 batch 中所有請求的 token 總量上限 | 與 KV cache 視訊記憶體直接相關 |
max_wait_time | 請求級動態批處理的最長等待視窗 | 通常 1–10ms 級別,需權衡延遲與吞吐 |
KV cache 預算 | 每個請求 prefill 後預留的 KV cache 頁數 | vLLM 中按 page 為單位管理,每頁含固定 token 數 |
chunked prefill | 將長 prompt 的 prefill 分塊執行,穿插 decode | 減少 prefill 對 decode 延遲的干擾 |
五、與 PagedAttention / KV Cache 管理的協同
Dynamic Batching 要求頻繁地”加入/退出”請求,這要求 KV cache 的分配和釋放足夠靈活:
- 傳統方式:為每個請求預分配連續的 KV cache 空間(按 max_seq_len),退出後才能釋放 → 碎片化嚴重。
- PagedAttention(vLLM 提出):將 KV cache 按固定大小的”頁”(page/block)管理,類似作業系統虛擬記憶體分頁。請求動態加入時按需分配頁,退出時頁立即可回收。
- 這樣 Dynamic Batching 才能在每個 iteration 靈活增減請求,不被 KV cache 碎片化所阻礙。
KV Cache 視訊記憶體管理對比:
傳統連續分配:
┌─────────┬─────────┬─────────┬─────────┐
│ Req A │ Req B │ Req C │ (空閒) │
│ (已結束)│ (還在跑)│ (還在跑)│ │
│ [浪費!] │ │ │ │
└─────────┴─────────┴─────────┴─────────┘
→ A 結束後其空間不能立即給 D 用(若不移動 C)
PagedAttention 分頁管理:
┌──┬──┬──┬──┬──┬──┬──┬──┐
│A1│B1│C1│D1│A2│B2│C2│空│ ← 每頁獨立,A 的頁可立即回收
└──┴──┴──┴──┴──┴──┴──┴──┘
→ A 結束後 A1、A2 立即可被新請求複用
技術演進史
| 時間 | 事件 | 意義 |
|---|---|---|
| ~2010s | 深度學習推論架構(TensorFlow Serving 等)引入基礎的請求級 dynamic batching | 允許在時間視窗內拼批,但仍是靜態 batch 執行 |
| 2022 | Orca 論文(OSDI’22,首爾大學 + 微軟研究院)提出 iteration-level scheduling | 首次系統化提出”連續批處理”:每一步排程、請求動態進出,從根本上消除 bubble |
| 2023 | vLLM(UC Berkeley)釋出,整合 PagedAttention + Continuous Batching | 將連續批處理與高效 KV cache 管理結合,成為開源 LLM 推論的事實標準引擎之一 |
| 2023 | NVIDIA TensorRT-LLM 引入 In-flight Batching | 商業推論棧跟進 continuous batching 概念 |
| 2023–2024 | Splitwise / DistServe 等提出 Prefill-Decode 分離 | 將 dynamic batching 推進到跨例項/跨節點級別 |
| 2024 | Chunked Prefill、Prefix Caching 等成為主流最佳化 | Dynamic Batching 與更多排程策略融合,排程器複雜度持續上升 |
| 2024–2025 | Disaggregated serving(PD 分離)在生產環境落地 | Dynamic Batching 從單節點排程器演變為叢集級排程系統 |
技術路線對比
| 維度 | 靜態批處理 (Static Batching) | 請求級動態批處理 (Request-level Dynamic) | 連續批處理 (Continuous Batching) | Prefill-Decode 分離 + 各自動態批處理 |
|---|---|---|---|---|
| 排程粒度 | 整個 batch 一次完成 | 每個 batch 一次完成,但 batch 內容動態組合 | 每個 decode step 排程一次 | 按階段(prefill/decode)獨立排程 |
| Bubble 現象 | 嚴重(短請求等長請求) | 有所緩解但仍存在 | 基本消除 | 完全消除 + 異構最佳化 |
| GPU 利用率 | 低(估算 30–50%,場景相關) | 中等(估算 50–70%) | 高(估算 80–95%+) | 最高(各階段匹配硬體特性) |
| 實現複雜度 | 低 | 中等 | 高(需要 iteration-level scheduler) | 很高(跨例項排程、網路傳輸 KV cache) |
| KV Cache 效率 | 浪費嚴重(預分配 max_len) | 有改善 | 高(配合 PagedAttention) | 最高 |
| 延遲公平性 | 差(長請求拖累短請求) | 有改善 | 好(短請求快速退出) | 最好 |
| 典型系統 | 早期 TF Serving, ONNX Runtime | NVIDIA Triton Dynamic Batching | vLLM, TensorRT-LLM, SGLang | Splitwise (研究) |
| 適用場景 | 離線批處理、對延遲不敏感 | 傳統 CV 模型推論 | LLM 線上推論(主流) | 大規模 LLM 叢集、追求極致吞吐和延遲 |
上下游
上游(依賴什麼)
┌─────────────────────────┐
│ 模型架構與引數 │
│ (決定 KV cache 大小、 │
│ prefill/decode 計算比) │
└───────────┬─────────────┘
│
┌──────────────────────┼──────────────────────┐
│ │ │
┌──────▼──────┐ ┌────────▼────────┐ ┌────────▼────────┐
│ GPU 硬體 │ │ 推論架構/引擎 │ │ KV Cache 管理 │
│ (視訊記憶體容量、 │ │ (排程器實現) │ │ (PagedAttention │
│ 頻寬、算力) │ │ │ │ 等) │
└─────────────┘ └─────────────────┘ └─────────────────┘
- GPU 視訊記憶體:決定了 max_batch_size、max_context_len 的上限,是 Dynamic Batching 引數空間的硬約束。
- 模型結構:注意力機制型別(MHA/MQA/GQA)影響 KV cache 大小,進而影響可同時服務的請求數。
- KV Cache 管理策略:PagedAttention、RadixAttention(SGLang)等是 Dynamic Batching 高效執行的基礎設施。
下游(影響什麼)
- 推論服務 API 的響應質量:TTFT(Time to First Token)、TPS(Tokens per Second)、端到端延遲。
- GPU 叢集利用率 → 單位推論成本($/M tokens)。
- API 定價策略:更高效的 batching → 更低的邊際成本 → 更具競爭力的定價。
- 使用者體驗:動態批處理使得高併發下仍能維持可接受的延遲 SLO。
關鍵指標
| 指標 | 含義 | 為什麼與 Dynamic Batching 相關 |
|---|---|---|
| Throughput (req/s 或 tokens/s) | 每秒處理的請求數或 token 數 | Dynamic Batching 直接提升吞吐 |
| TTFT (Time to First Token) | 從請求到達到第一個 token 輸出的時間 | Prefill 階段被長 batch 中其他請求延遲 → batching 策略影響 TTFT |
| TPOT (Time Per Output Token) | 每個輸出 token 的平均生成時間 | Decode 階段 batch 越大,單 token 延遲可能增加(但吞吐提升) |
| P50/P99 Latency | 延遲分位數 | Dynamic Batching 需要在平均吞吐和尾部延遲間權衡 |
| GPU Utilization / SM Occupancy | GPU 計算單元利用率 | 好的 batching 策略讓 GPU 始終”吃飽” |
| KV Cache Utilization | KV cache 視訊記憶體的使用效率 | PagedAttention 減少碎片化,直接支撐更靈活的 batching |
| Goodput | 滿足 SLO 的有效吞吐 | 不僅看吞吐,還要看多少請求在延遲約束內完成 |
供需與市場資料
需求端
- LLM 推論請求的特徵:輸入輸出長度高度不確定、即時性要求高、併發波動大。這些特徵使得 Dynamic Batching 不是”錦上添花”而是”剛需”。
- 隨著 Agent / RAG / 長上下文應用爆發,單請求 token 數上升,對 batching 策略的精細化要求更高。
供給端
- 開源引擎競爭激烈:vLLM、SGLang、TensorRT-LLM 在 batching 策略上持續迭代,是社群最活躍的最佳化方向之一。
- 雲端廠商差異化:各大雲端廠商的推論服務(如 AWS SageMaker、Azure ML、Google Vertex AI)在底層均實現了某種形式的 Dynamic Batching / Continuous Batching,差異主要體現在排程精細度和與硬體的協同最佳化上。
- 推論晶片廠商:除 NVIDIA 外,AMD(ROCm + vLLM 支援)、華為昇騰(MindSpore Serving)等也在跟進。
市場規模
Dynamic Batching 本身不是一個獨立市場,而是推論引擎/推論服務的核心技術元件。其價值體現在推論服務市場的規模中——據多家行業報告估算,全球 LLM 推論服務市場在 2025 年已達數百億美元量級,且仍在高速增長。Dynamic Batching 的最佳化直接影響該市場的獲利率結構。
代表公司與資本對映
| 公司/專案 | 角色 | 與 Dynamic Batching 的關係 |
|---|---|---|
| NVIDIA | 推論硬體 + 軟體棧 | TensorRT-LLM 的 In-flight Batching;Triton 的 Dynamic Batching;在 disaggregated serving 方向持續探索 |
| vLLM (UC Berkeley → Anyscale/社群) | 開源推論引擎 | 連續批處理 + PagedAttention 的標杆實現,廣泛被企業和雲端廠商採用 |
| SGLang (UC Berkeley) | 開源推論引擎 | 在 continuous batching 基礎上加入 RadixAttention(字首快取)、compressed FSM 等,面向結構化輸出最佳化 |
| CoreWeave | GPU 雲端服務 | 底層推論服務依賴高效的 batching 策略來最大化 GPU 利用率 |
| Lambda / Together AI / Fireworks AI | 推論 API 服務商 | 自研或基於 vLLM/TRT-LLM 的 batching 最佳化是核心競爭力之一 |
| Anyscale | Ray + 推論平台 | Ray Serve 提供了生產級的 batching 入口,vLLM 的重要貢獻方 |
| Anthropic / OpenAI / Google DeepMind | 模型推論方 | 內部推論基礎設施必然採用先進的 dynamic/continuous batching,但具體實現未公開 |
產業對映
核心判斷
- Dynamic Batching 是推論側”降本增效”的核心槓桿:在模型引數量和推論需求同步增長的背景下,不最佳化 batching 意味著 GPU 利用率低下 → 推論成本高企 → 無法支撐大規模應用落地。
- 開源引擎(vLLM、SGLang)的快速迭代正在壓縮商業推論棧的差異化空間:純靠 batching 策略難以構成持久壁壘,真正的壁壘在於與硬體的深度協同(如 NVIDIA 全棧)或與上層應用的深度整合。
- Prefill-Decode 分離是下一階段工程焦點:在叢集級別實現高效排程(包括 KV cache 的跨節點傳輸)的平台,能在大規模推論場景下獲得顯著的成本優勢。這催生了對高頻寬互聯(如 NVLink、RoCE、定製交換器)的需求。
受益標的型別
- GPU/加速器廠商(NVIDIA、AMD 等):更高效的 batching → 更高的 GPU 利用率 → 客戶同樣的業務需求下 GPU 採購量可能減少,但推論市場規模增長抵消這一影響;同時 software stack 的 batching 能力成為差異化賣點。
- 推論服務公司(CoreWeave、Together AI 等):batching 效率直接影響獲利率。
- 推論晶片創業公司:如果能證明在特定場景下更優的 batching+硬體協同方案,存在差異化機會。
- 網路/互聯基礎設施:PD 分離架構對節點間 KV cache 傳輸的頻寬和延遲提出新需求。
常見誤讀糾偏
❌ 誤讀 1:“Dynamic Batching 就是 Continuous Batching”
糾偏:兩者相關但不等價。
- Dynamic Batching(廣義):泛指任何動態組合請求的批處理策略,包括請求級時間視窗內的拼批。
- Continuous Batching(特指 iteration-level scheduling):是 Dynamic Batching 的一種更高階形式,排程粒度從”請求批次”細化到”每個 decode step”,允許請求每一步動態進出。
- 很多早期文章將 Triton 的”Dynamic Batching”等同於後續的”Continuous Batching”,但實際上 Triton 的 Dynamic Batching 仍是請求級的——它在時間視窗內收集請求拼批,但一旦批開始執行,內部的請求就不再變化。
❌ 誤讀 2:“Batch 越大,延遲越低”
糾偏:Batch 越大,吞吐越高,但單請求延遲通常不降反升。
- 增大 batch → GPU 並行度提升 → 總吞吐(tokens/s)上升。
- 但更大的 batch 意味著每個請求在 GPU 上排隊等更多並行任務 → 單請求延遲(特別是 decode 階段的 TPOT)可能增加。
- Dynamic Batching 的精妙之處在於:不做一刀切的大 batch,而是根據即時負載自適應調整 batch 大小,在吞吐和延遲之間尋找最優解。
❌ 誤讀 3:“有了 Dynamic Batching 就不需要關心模型優化了”
糾偏:Dynamic Batching 是系統層最佳化,不能替代模型層最佳化。
- 模型層:量化(INT8/INT4)、剪枝、知識蒸餾、MQA/GQA 減少 KV cache → 直接降低每個請求的資源佔用。
- 系統層:Dynamic Batching、PagedAttention、kernel fusion → 提升資源利用效率。
- 兩者是乘法關係:模型越輕量,同樣的 batch 容量下能放更多請求;batching 越高效,模型最佳化帶來的單位收益被放大。
❌ 誤讀 4:“Prefill 和 Decode 應該總是一起做 batching”
糾偏:Prefill 和 Decode 的計算特徵截然不同,混在一起 batching 會互相干擾。
- Prefill 計算密集(高 arithmetic intensity),可以充分利用 GPU 的算力。
- Decode 訪存密集(低 arithmetic intensity),瓶頸在 HBM 頻寬。
- 一個長 prompt 的 prefill 會阻塞同 batch 中正在 decode 的請求(增加其 TPOT),反之 decode 的低算力利用拉低了 prefill 的效率。
- 2024 年以來的研究趨勢(Splitwise、DistServe 等)正是將兩者分離到不同例項上,各自做最優的 batching 策略。
學習路徑
Level 0: 理解 LLM 推論基本流程
└─ 什麼是 prefill、什麼是 decode、什麼是 KV cache
└─ 推薦: 任意一篇 "LLM Inference Explained" 的部落格
Level 1: 理解 batching 的基本概念
└─ 為什麼需要 batching(GPU 平行計算 vs 序列請求)
└─ 靜態批處理的問題(padding 浪費、bubble)
└─ 推薦: NVIDIA Triton 官方文件中的 Dynamic Batching 章節
Level 2: 閱讀核心論文
└─ Orca (OSDI'22): "Orca: A Distributed Serving System for Transformer-Based Generative Models"
└─ 理解 iteration-level scheduling 的設計動機和實現
└─ vLLM (SOSP'23): "Efficient Memory Management for Large Language Model Serving with PagedAttention"
└─ 理解 PagedAttention 如何支撐靈活的 dynamic batching
Level 3: 讀原始碼 / 動手實驗
└─ vLLM 原始碼中的 `Scheduler` 類 → 理解 waiting/running/swap 狀態機
└─ SGLang 原始碼中的 `Scheduler` → 對比不同調度策略
└─ 用 vLLM 本地部署一個模型,調整 `max_num_seqs`、`max_num_batched_tokens` 觀察延遲/吞吐變化
Level 4: 關注前沿
└─ Prefill-Decode 分離 (Splitwise, DistServe)
└─ Chunked Prefill 的排程策略
└─ 多模態推論中的 batching(影像/影片 token 與文本 token 的異構排程)
└─ Speculative Decoding 與 batching 的互動
一句話總結
Dynamic Batching 是 LLM 推論引擎的靈魂排程策略——從請求級拼批到迭代級連續批處理再到 Prefill-Decode 分離,其演進方向始終是”讓 GPU 每一納秒都在做有效計算”,是推論成本曲線下降的關鍵推手。
延伸閱讀與來源
- Orca: A Distributed Serving System for Transformer-Based Generative Models — Yu et al., OSDI 2022. (連續批處理 / iteration-level scheduling 的奠基論文)
- Efficient Memory Management for Large Language Model Serving with PagedAttention — Kwon et al., SOSP 2023. (vLLM / PagedAttention 論文)
- SGLang: Efficient Execution of Structured Language Model Programs — Zheng et al., 2024. (RadixAttention)