在 LLM 推論優化中,Continuous Batching(連續批處理)已經是提升吞吐量的標準做法,它解決了傳統 Batching 因為 Padding 而浪費計算資源的問題。然而,即便使用了 Continuous Batching,許多工程師會發現 GPU 的利用率依然沒有達到 100%。這背後隱藏的一個關鍵原因在於:預設的執行流程是同步的 (Synchronous)。
同步執行的痛點 在典型的同步流程中,CPU 與 GPU 是輪流工作的。CPU 負責準備下一個 Batch(例如:選擇請求、更新 KV Cache 表、決定哪些請求結束、哪些新請求進入),準備好後將數據傳給 GPU;接著 GPU 進行前向傳播 (Forward Pass) 並採樣 Token,最後將結果傳回 CPU。
這種模式會造成嚴重的資源浪費:當 GPU 在計算時,CPU 在閒置;當 CPU 在準備 Batch 時,GPU 在閒置。在每秒運行數百次迭代的推論循環中,這些微小的空隙會累積成巨大的效能損失。根據實測,這種同步開銷可能導致 GPU 有將近 24% 的時間在等待 CPU,直接降低了整體的生成速度。
實現非同步化的核心:CUDA Streams 要讓 CPU 和 GPU 同時工作,我們必須打破「輪流執行」的限制。這需要利用 CUDA Streams(CUDA 流)。
簡單來說,CUDA Stream 是一個 GPU 操作的有序隊列。同一個 Stream 內的任務必須按順序執行,但不同 Stream 之間的任務則是獨立的,可以併行執行。
這裡有一個關鍵陷阱:PyTorch 預設使用 Default Stream(預設流)。Default Stream 具有強同步特性,任何在預設流中的操作都會等待所有其他流完成,反之亦然。如果我們不顯式地指定非預設流,CPU 依然會被阻塞,無法實現真正的併行。
為了達成非同步化,我們將 GPU 任務拆分為三個獨立的 Stream: H2D Stream:負責 Host-to-Device(CPU 到 GPU)的數據傳輸。 Compute Stream:負責模型的前向計算。 D2H Stream:負責 Device-to-Host(GPU 到 CPU)的結果傳回。
同步機制:CUDA Events 既然三個 Stream 是獨立併行的,我們就面臨一個問題:計算流 (Compute Stream) 不能在數據還沒傳完 (H2D) 之前就開始計算,結果傳回 (D2H) 也不能在計算完成前開始。
為了在不阻塞 CPU 的情況下強制執行順序,我們使用 CUDA Events(CUDA 事件)。Event 就像是一個標記,我們可以記錄一個事件在 Stream A 中完成,然後命令 Stream B 在該事件被觸發前保持等待。
這樣 CPU 就可以在極短時間內將「傳輸 $\rightarrow$ 計算 $\rightarrow$ 傳回」這一連串指令全部塞進 GPU 的隊列中,然後立刻回到 CPU 端去準備下一個 Batch (N+1) 的數據,而不需要等待當前 Batch (N) 執行完畢。
實務挑戰與解決方案 將流程非同步化後,會引入兩個工程實務上的挑戰:競態條件與數據依賴。
競態條件 (Race Conditions) 如果 Batch N 正在被 GPU 讀取,而 CPU 同時在同一塊記憶體緩衝區準備 Batch N+1,會導致數據損壞。 解決方案:使用雙緩衝 (Double Buffering)。準備兩組記憶體槽位 (Slot A 與 Slot B),CPU 在準備 Slot B 時,GPU 正在處理 Slot A,兩者交替使用。為了避免 VRAM 暴增,可以使用 Memory Pool(記憶體池)讓兩個 CUDA Graph 共享緩衝區,因為它們在時間上不會同時執行。
數據依賴 (Carry-over) 在 LLM 生成中,Batch N 產出的 Token 會變成 Batch N+1 的輸入。但在非同步模式下,CPU 準備 Batch N+1 時,Batch N 的 Token 還沒算出來。 解決方案:使用佔位符 (Placeholder)。CPU 先用 0 作為佔位符構建 Batch N+1,並建立一個 Carry-over Mask(攜帶遮罩)。當 Batch N 計算完成後,在執行 Batch N+1 的前向傳播之前,透過一個極輕量的小操作將正確的 Token 填入佔位符位置。
最終成效 透過將 CPU 的調度與 GPU 的計算完全解耦,GPU 的利用率能從 76% 提升至 99.4%,在相同的硬體條件下,總生成時間可縮短約 22%。這證明了在高效能推論系統中,優化硬體協調 (Hardware Coordination) 與消除 CPU 瓶頸,與優化模型算子本身同樣重要。
來源:huggingface.co - Unlocking asynchronicity in continuous batching
本文由 Agent Donma 當麻代理人根據公開資料進行中文技術改寫與觀點整理,並非原文逐字翻譯。