iT邦幫忙

2026 iThome 鐵人賽

DAY 15
0
Software Development

LLM infra 學習日記系列 第 15

Continuous Batching:Batch 為什麼可以中途換人?

  • 分享至 

  • xImage
  •  

昨天 vLLM Engine Core 的主迴圈:

schedule → execute → update

關鍵是這個迴圈只推進一個 engine step,不會把整批 requests 一次跑到結束。

因此每一步結束後,Scheduler 都能重新決定下一步的 batch。這就是 Continuous Batching,也常被稱為 iteration-level scheduling 或 in-flight batching。

先說清楚:今天只有概念與 source tracing,沒有執行 benchmark。


Static Batching 卡在哪裡?

一般的 batching 會先收集一批輸入,再一起執行。但 LLM decode 和影像分類不同:每條 request 要產生幾個 tokens,事前並不知道。

如果 batch 成員從開始到結束都固定:

短 request 先完成 → 留下一個不能補人的空位
新 request 抵達     → 必須等待整個 batch 結束

GPU 仍在跑最長的 request,但 batch 已經愈來愈小。

Dynamic batching 有時只是「多等幾毫秒,把同時抵達的 requests 湊成一批」;如果 batch 啟動後仍不能換人,問題並沒有消失。


一個紙上 workload

假設同時最多容納兩條 sequences,忽略 Prefill 成本;每格代表一條 request 完成一次 decode iteration:

Request 抵達時間 需要的 decode iterations
A Step 1 前 4
B Step 1 前 2
C Step 1 後 2

Static batch

Step Slot 1 Slot 2
1 A B
2 A B 完成
3 A
4 A 完成
5 C
6 C 完成

C 必須等 A 所在的 batch 結束,六個 steps 中出現四個空 slots。

Continuous batch

Step Slot 1 Slot 2
1 A B
2 A B 完成
3 A C
4 A 完成 C 完成

B 完成後,C 在下一個 step 補進來。相同八次有效 decode iterations,在這個簡化例子裡由六個 steps 降為四個。

這只是排程示意,不是 latency benchmark。真實 step 時間還會受 batch 內 token 數、context length、Prefill、硬體與 kernel 影響。


vLLM 每一步怎麼換人?

在目前的 vLLM V1 Scheduler 中,requests 主要位於 waitingrunning queue。一次 step 可以簡化成:

1. 先檢查 running requests 下一步需要計算多少 tokens
2. 在 token budget 內配置新的 KV Cache slots
3. 若 sequence 容量與 budget 還有空間,再從 waiting queue 加入 requests
4. 執行這一輪 model forward
5. 更新輸出;完成的 request 退出並釋放資源
6. 下一個 step 重新排程

因此「batch」不是一個從頭到尾不變的 tensor 群組,而是 Scheduler 為這個 step 產生的工作集合。

目前 V1 是 unified scheduler。它不必先把 request 永久標成 Prefill 或 Decode,而是用類似下面的資料描述這一步:

{request_id: num_tokens_to_compute}

一般 decode request 通常前進一個 token;Prefill request 則可能一次排入許多 tokens。兩者能出現在同一套 token budget 裡。


不是有空位就一定能加入

Continuous Batching 仍受幾個上限約束:

  • max_num_seqs:單一 iteration 最多處理多少 sequences。
  • max_num_batched_tokens:單一 iteration 最多處理多少 tokens。
  • KV Cache:是否還有足夠 blocks 容納新 request。
  • Scheduling policy:目前可使用 FCFS 或 priority scheduling。

所以新 request 抵達後只是取得「下一步可以被考慮」的機會;資源不足時仍然要等待,甚至可能觸發 preemption。

這也解釋了 PagedAttention 和 Continuous Batching 為什麼常一起出現:前者讓每條 request 的 KV Cache 可以用 blocks 動態增長與釋放,後者才能更靈活地讓 batch 成員進出。


Continuous 不代表所有 latency 都會變好

Continuous Batching 的主要收益是減少空 slots,讓 GPU 在有併發流量時維持較大的有效 batch,通常有利於 throughput,也能縮短新 request 等待下一批的時間。

但它也會帶來干擾:如果 Scheduler 把一個很長的 Prefill 一次塞進正在 Decode 的 batch,這個 step 會變久,其他 requests 的 inter-token latency 也可能上升。

所以真正的問題不只是在 batch 中途補人,還要決定:

一條很長的 prompt,應不應該一次把全部 tokens 排進去?

這就是明天的 Chunked Prefill。


今天的結論

Static Batching
固定 batch 成員,最慢的 request 決定何時換下一批

Continuous Batching
每個 iteration 重新排程,完成一條就能補進一條

它沒有改變 autoregressive generation 一次產生下一個 token 的本質;它改變的是 Scheduler 與 execution engine 互動的粒度:

request-level → iteration-level

而在 vLLM 裡,這個機制必須和 token budget、KV Cache blocks、Prefill 與 Decode 一起考慮。

Reference


上一篇
一個 Request 怎麼走進 vLLM?從 API 到下一個 Token
下一篇
Chunked Prefill:讓長 Prompt 不要卡住正在生成的 Request
系列文
LLM infra 學習日記19
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言