在生成式 AI 與大語言模型(LLM)落地生產環境的過程中,「推理效能與 GPU 顯存成本」 是決定業務能否盈利的生死線。

許多工程師初次部署開源大模型(如 Llama 3 70B 或 Qwen 2.5)時,常會發現:即使配備了昂貴的 8x H100 GPU 伺服器,當併發請求數(Concurrent Requests)稍一上升,系統就會因為顯存溢出(OOM, Out of Memory)而崩潰,或是每秒處理 Token 數(Tokens/sec)低得令人無法接受。

LLM 的自迴歸(Autoregressive)生成特性,決定了其推理過程包含兩個特性完全相反的階段:Prefill 階段與 Decode 階段。其中產生的 KV Cache 更是吞噬 GPU 記憶體的頭號元兇。

加州大學柏克萊分校發表的經典論文 vLLM: Efficient Memory Management with PagedAttention (SOSP 2023) 透過作業系統虛擬記憶體的分頁思想,徹底顛覆了 LLM 推理架構。

本文基於 vLLM 論文、Hugging Face TGI 與 ByteByteGo System Design 101,深度剖析大模型推理優化的核心演算法與工程實踐。

大模型推理引擎優化與 PagedAttention 記憶體架構展示 Prefill/Decode 雙階段特徵、KV Cache 記憶體碎片化痛點、vLLM PagedAttention 虛擬分頁區塊映射,以及 Continuous Batching 與推測解碼加速機制。INFERENCE PHASES & PAIN推理階段與記憶體痛點Prefill vs Decode 階段• Prefill:計算密集型 (Compute-Bound, TTFT)• Decode:記憶體頻寬受限 (Memory-Bound, ITL)⚠️ 傳統 KV Cache 碎片化• 預先分配 Max-Seq-Len (如 8K)• 內部碎片 (未用完) + 外部碎片 (不連續)• 浪費 60% ~ 80% 昂貴 GPU 顯存!吞吐量瓶頸• 顯存不足限制最大併發 Batch Size• 靜態 Padding 浪費大量計算週期VLLM PAGEDATTENTION虛擬分頁區塊映射架構Logical Block TableReq 1: [L0➔P7] [L1➔P2] [L2➔P9]Req 2: [L0➔P7] [L1➔P5] (Fork 共享)• 按需動態分配 Fixed-Size Block (如 16 Tokens)零拷貝分叉 (Copy-on-Write)• Beam Search 與 Parallel Sampling• 多分支共享 System Prompt 物理區塊• 僅在寫入不同 Token 時複製 (COW)極致顯存利用率• 碎片化降至 < 4% (近乎零浪費)• 併發 Batch Size 提升 4x ~ 5x!ACCELERATION PIPELINES動態批處理與推測解碼Continuous Batching• Iteration-level 動態調度• 請求隨到隨入,結束即退出釋放• 徹底消除靜態 Padding 浪費• GPU 算力飽和度逼近 100%推測解碼 (Speculative Decoding)• Draft 小模型高速生成 K 個候選詞• Target 大模型 1 次 Forward 驗證全批次• 數學嚴格保證輸出分佈完全一致• 解碼延遲降低 2x ~ 3x!
STEP 1: PHASES & BOTTLENECK

Prefill 與 Decode 階段

Prefill 屬於計算密集型,Decode 屬於記憶體頻寬受限。傳統靜態分配 KV Cache 造成 60%~80% 顯存碎片浪費。

↓ 虛擬分頁區塊管理
STEP 2: PAGEDATTENTION

vLLM 虛擬分頁映射

借鑒作業系統虛擬記憶體,以 16 Token 為單位動態分配物理區塊,支援 Beam Search 零拷貝共享,顯存利用率提升至 96%+。

↓ 吞吐與延遲極致優化
STEP 3: ACCELERATION

Continuous Batching 與推測解碼

Iteration-level 動態批處理消除 Padding,搭配 Draft 小模型推測驗證,系統吞吐量暴增 4~5 倍。

圖 1:大模型推理引擎優化、vLLM PagedAttention 記憶體管理與推測解碼架構

一、Prefill 階段 vs. Decode 階段:兩種完全不同的效能瓶頸

Transformer 模型在生成文本時,每個 Request 都必須經歷兩個截然不同的計算階段:

1. Prefill 階段(首字生成階段 / Prompt Processing)

  • 任務:接收使用者輸入的完整 Prompt(例如 2,000 字),計算所有輸入 Token 的 Self-Attention 矩陣,並生成第一個 Output Token。
  • 瓶頸特徵:計算密集型(Compute-Bound)。所有輸入 Token 可以透過 GEMM(矩陣乘法)完全平行並發計算,GPU 運算核心(Tensor Cores)利用率接近飽和。
  • 核心指標:TTFT(Time-to-First-Token,首字延遲)。

2. Decode 階段(自迴歸逐字生成階段 / Token Generation)

  • 任務:每次將新生成的 1 個 Token 與過去所有的歷史 Token 結合,預測下 1 個 Token。
  • 瓶頸特徵:記憶體頻寬受限(Memory-Bound)。每生成僅僅 1 個 Token,GPU 都必須從顯存(HBM)中完整載入數十 GB 的模型權重矩陣與全量歷史 KV Cache!
  • 核心指標:ITL(Inter-Token Latency,詞間生成延遲) 與每秒整體吞吐量。

二、KV Cache 為何浪費 60% ~ 80% 的 GPU 顯存?

在 Attention 計算中:

Attention(Q, K, V) = softmax((Q * K^T) / sqrt(d_k)) * V

在自回歸解碼(Autoregressive Decoding)過程中,每生成一個新 Token,模型需要與歷史上所有的 Token 計算注意力。為了避免重複計算歷史 Token 的 Key 和 Value 向量,系統會將歷史各層的 K 與 V 矩陣快取在顯存中——這就是 KV Cache。

1.2 KV Cache 顯存容量估算公式

每個 Token 所需的 KV Cache 顯存大小計算公式為:

KV_Size_Per_Token = 2 * n_layers * n_heads * d_head * precision_bytes

以 Llama 3 70B(80 層、8 個 KV Heads、Head Dim 128、FP16 2 Bytes)為例:

  • 單一 Token 的 KV Cache = 2 * 80 * 8 * 128 * 2 Bytes = 327,680 Bytes ≈ 320 KB。
  • 若 Context 長度達到 8,192(8K),單一併發請求就需要佔用 2.56 GB 顯存!
  • 若同時有 100 個併發請求,僅 KV Cache 就需要 256 GB 顯存,遠遠超過模型權重本身!

2. 傳統推理框架的碎片化危機(Fragmentation)

在 vLLM 出現前,傳統系統(如 Hugging Face Transformers / FasterTransformer)採用靜態連續記憶體分配:

  1. 內部碎片(Internal Fragmentation):由於無法預知用戶請求會生成多少字,系統必須預先為每個請求分配最大長度(如 Max-Seq-Len = 8K)。若用戶只生成了 200 字就結束,剩餘 7.8K 的顯存空間全部被白白浪費!
  2. 外部碎片(External Fragmentation):請求長短不一,不同長度的動態分配在顯存中產生大量無法利用的離散空洞。
  3. 保留碎片(Reservation Fragmentation):為未來可能生成的 Token 提前鎖定顯存配額。

三、vLLM 革命:PagedAttention 虛擬分頁區塊架構

vLLM 的核心突破在於:將作業系統管理記憶體分頁(Paging)的機制引入了 GPU 顯存管理。

1. Logical Block Table 映射機制

  • vLLM 將每個序列的 KV Cache 邏輯上切分為固定大小的 Block(如每個 Block 容納 16 個 Tokens)。
  • 物理顯存不再要求連續存放,而是劃分為一個個不連續的物理塊池(Physical Block Pool)。
  • 透過 Block Table 記錄邏輯塊到物理塊的動態映射(類似 OS 的 Page Table):
PagedAttention 邏輯分塊到不連續物理顯存塊映射圖展示 Request 1 的邏輯塊 0 映射至物理塊 7、邏輯塊 1 映射至物理塊 2、邏輯塊 2 按需映射至物理塊 9。Request 1 邏輯序列 (Logical Blocks)Logical Block 0 (Token 0..15)Logical Block 1 (Token 16..31)Logical Block 2 (Token 32..47)GPU 物理顯存塊池 (Physical HBM)Physical Block #7 (Slot 0..15)Physical Block #2 (Slot 16..31)Physical Block #9 (按需即時動態分配)

2. 零拷貝分叉與共享(Copy-on-Write)

在平行採樣(Parallel Sampling,如一次生成 3 個回答)或 Beam Search 時,多個分支共享相同的 Prompt 前綴:

  • 傳統做法:必須複製多份完整的 Prompt KV Cache。
  • PagedAttention:多個邏輯序列直接指向相同的物理 Block,引用計數(Reference Count)加 1。
  • 只有當某個分支開始生成不同的新 Token 時,才觸發 Copy-on-Write(寫時複製),節省高達 55% 以上的顯存!

四、Continuous Batching(持續動態批處理)

傳統批處理(Static Batching)必須等待批次中最長的請求生成完畢才能結束,導致短請求結束後 GPU 計算單元大量空轉等待(Padding Waste)。

Continuous Batching(迭代級動態調度) 徹底改變了調度粒度:

Continuous Batching 持續動態批處理 vs 傳統 Static Batching 對比圖展示 Static Batching 短請求結束後需 Padding 等待長請求浪費算力,而 Continuous Batching 在 Iteration 級別立即插隊新請求提升利用率至 95%。❌ Static Batching (傳統靜態批次:存在大量 Padding 空轉浪費)Req A (50t)Padding 浪費等待 (150t 空轉)Req B (200 tokens 長請求)✅ Continuous Batching (vLLM 迭代級動態插隊:95% 算力飽和)Req A (50t 完成)⚡ Req D 立即無縫插隊執行 (130t)Req B (200 tokens 持續並行生成)吞吐量提升 3 ~ 4 倍,GPU HBM / Tensor Core 全程無空轉!
  • 在每一次 Token 迭代(Iteration-Level)結束時,檢查是否有已完成的請求;
  • 一旦請求完成,立即釋放其物理 Block,並在下一輪迭代中無縫插入新的請求。
  • GPU 算力利用率達到 95% 以上,吞吐量提升 3 ~ 4 倍。

五、Speculative Decoding(推測解碼):打破自迴歸速度極限

Decode 階段每次 Forward 只能產生 1 個 Token。推測解碼(Speculative Decoding) 利用「大模型驗證比生成快」的數學特性打破這一瓶頸:

  1. Draft 小模型高速生成:使用輕量級模型(如 Llama-3-8B 作為 70B 的 Draft)快速推測生成 K 個 Token(例如 K = 5)。
  2. Target 大模型單次驗證:大模型在僅僅 1 次 Forward Pass 中同時評估這 5 個候選 Token 的條件機率分佈。
  3. 拒絕採樣(Rejection Sampling):
    • 若前 3 個 Token 命中分佈,則全部接受;第 4 個若偏離則拒絕並即時修正。
    • 數學嚴格證明:最終輸出文本的機率分佈與大模型單獨生成完全等價(Lossless Quality)。
  4. 效果:每次大模型前向傳播平均可產生 2 ~ 3 個 Token,端到端推理延遲降低 50% ~ 70%。

六、生產環境落地最佳實踐

  1. 量化加速(Quantization):採用 AWQ(Activation-aware Weight Quantization) 或 FP8 格式,將模型權重由 16 位元壓縮至 4/8 位元,大幅降低記憶體頻寬壓力。
  2. Chunked Prefill:將超長 Prompt 切片與 Decode 請求混合批處理,避免超長 Prompt 霸佔 GPU 導致短請求產生嚴重的 TTFT 尖刺。
  3. 前綴快取(Prefix Caching):在 Agent 或 RAG 場景中開啟 enable_prefix_caching=true,自動複用多輪對話中相同的 System Prompt 與知識庫檢索上下文。