【vLLM 工程師實戰】#03 榨乾吞吐量:連續批次、並行與量化的調校手冊

測驗:vLLM 榨乾吞吐量

共 5 題,點選答案後會立即顯示結果

1. 關於 continuous batching(連續批次),文章的白話比喻是什麼?

  • A. 像公車,要等座位坐滿才發車
  • B. 像共乘計程車,車在路上跑、有人到就併進來、有人到站就放下
  • C. 需要工程師手動寫 code 觸發它才會運作
  • D. 只有量化模型才支援的特殊功能

2. --tensor-parallel-size 2 這個參數在做什麼?

  • A. 一次最多處理 2 個請求
  • B. 把模型量化成 2-bit
  • C. 把一個模型切開攤到 2 張 GPU 上一起算
  • D. 限制一批最多 2 個 token

3. 你觀察到「吞吐量偏低,但 GPU 使用率一直沒滿」,最可能該調哪個參數?

  • A. 調低 --tensor-parallel-size
  • B. 換一個精度更高的 --dtype
  • C. 調高 --max-num-batched-tokens,把批次喂飽
  • D. 拿掉 --quantization

4. 關於 --quantization awq,文章強調的關鍵前提是什麼?

  • A. 它會在載入時即時把原版模型壓成 4-bit
  • B. 它是用 AWQ 方式讀「本身已是 AWQ 量化版」的模型,載入的模型名稱必須是量化版
  • C. 只要顯存夠,任何模型都該加上它
  • D. 它會自動提高模型精度

5. 壓測報告裡的 TTFT(Time To First Token)偏高,代表使用者感受到的是什麼?

  • A. 盯著空白畫面乾等,第一個字遲遲不出來
  • B. 字一個一個慢慢蹦、打字不流暢
  • C. 整台機器每秒總產出變低
  • D. 模型回答的精度下降

系列第 3 篇,共 4 篇 | 難度:L2-進階
前置知識:已讀第 1、2 篇,理解 vllm serve 怎麼把模型跑起來、KV Cache 與 --gpu-memory-utilization 這些記憶體參數。

這篇要解決的問題

第 1、2 篇你已經能把模型 serve 起來、也知道 KV Cache 會吃掉多少顯存。但真正上線後,老闆問的是另一件事:

「同時 50 個人打過來,會不會卡?一張卡到底能扛多少 QPS?跑不動了要加卡還是換量化?」

這篇就是教你怎麼「看懂吞吐量的旋鈕」。重點不是要你手刻推論引擎——continuous batching 這些核心機制 vLLM 自動幫你做好了——而是讓你看懂 AI 或同事丟給你的啟動指令有沒有問題、壓測數字往哪個方向調

你是驗收者:AI 很會生一長串 vllm serve 參數,但它常常把 --tensor-parallel-size 設錯、或量化模型名稱張冠李戴。你要能一眼認出紅旗。


一句話說明:continuous batching

白話: 請求隨到隨併進正在跑的那批,不用等湊滿一車才發車。

傳統 batching 像公車——要等座位坐滿(或等時間到)才開,先到的人得乾等。continuous batching(連續批次,vLLM 又叫 in-flight batching)像共乘計程車——車在路上跑,有人要上車就在下一個路口併進來,有人到站就放下,車一直是滿載狀態。

傳統 batch[req1 req2] 一起跑完 → 才收 [req3 req4]
  req3 到得早也得等 req1req2 全部生成完

continuous batchvLLM 預設):
  req1 生成中 ... req2 併入 ... req1 結束、req3 補位 ...
  每個 decode step 重新組批,GPU 永遠不閒置
Code language: CSS (css)

你要知道的只有一件事:這是自動發生的,vLLM 預設就開著。 你不用寫任何 code 去觸發它。你要做的是餵給它對的參數,讓「這台共乘車」能載更多人。

🚦 為什麼工程師要在乎它

因為它決定了兩個此消彼長的指標:

  • Throughput(吞吐量):整台伺服器每秒能吐多少 token / 服務多少請求。批次越大越高。
  • Latency(延遲):單一使用者感受到的快慢。批次太大時,你的請求要跟一堆人搶 GPU,反而變慢。

continuous batching 讓你在高吞吐的同時盡量不犧牲延遲,但天下沒有白吃的午餐——批次塞越滿,個別請求的延遲就越容易被拉高。調校就是在這條線上找你場景要的平衡點。


關鍵旋鈕:五個你會反覆看到的參數

AI 生成的啟動指令通常長這樣(最小可讀版本):

vllm serve Qwen/Qwen2.5-7B-Instruct \
  --tensor-parallel-size 2 \
  --max-num-seqs 256 \
  --max-num-batched-tokens 8192 \
  --quantization awq \
  --dtype auto

一行一行翻譯成白話:

參數 這在幹嘛 調大會怎樣
--tensor-parallel-size(TP) 把一個模型「切開」攤到幾張 GPU 上 能跑更大的模型,但卡間通訊有開銷
--max-num-seqs 一批最多同時處理幾個請求(併發數上限) 吞吐↑,但延遲可能↑、顯存↑
--max-num-batched-tokens 一個 step 最多處理幾個 token(batch 的「總容量」) 吞吐↑,設太小會卡住吞吐
--quantization 用哪種量化格式壓縮權重(awq/gptq/fp8…) 省顯存、可提併發,但精度略降
--dtype 權重的運算精度(auto/float16/bfloat16) 通常放 auto 就好

--tensor-parallel-size(TP):把模型攤到多張卡

--tensor-parallel-size 2   # 這顆模型拆成 2 份,用 2 張 GPU 一起算
Code language: PHP (php)

白話: 一顆 70B 的模型單張卡塞不下,就把它「橫著切開」分給 2 張、4 張卡,大家算自己那塊、再把結果合起來。

必看懂:TP 數 = 你要用幾張卡跑「這一個」模型。TP=1 就是單卡。

🚩 紅旗(後面詳談):TP 數必須能整除模型的 attention head 數,而且通常設成你實際有的 GPU 張數。AI 很愛複製別人的指令,把 --tensor-parallel-size 4 貼到你只有 2 張卡的機器上——啟動直接爆。

--max-num-seqs vs --max-num-batched-tokens:兩個容量上限

這兩個最容易搞混,用一句話分開:

  • --max-num-seqs幾個人能同時上車(請求數)。
  • --max-num-batched-tokens:這批總共幾個 token 的處理量(工作量)。

vLLM 每個 step 會在「不超過這兩個上限」的前提下,盡量把在排隊的請求塞進批次。哪個先撞到上限,就由哪個決定這批多大。

情境:一堆長 prompt(各 4000 token)湧入
  max-num-batched-tokens = 8192 → 一批只塞得下 2 個(8192 / 4000 ≈ 2)
  就算 max-num-seqs = 256,也輪不到,token 上限先卡住

所以如果你看到吞吐上不去、GPU 使用率卻沒滿,很多時候是 --max-num-batched-tokens 設太小,批次根本喂不飽 GPU。


量化取捨:什麼時候該壓、壓了會怎樣

量化(quantization)= 把模型權重從 16-bit 壓成 8-bit 或 4-bit,換取更少顯存、更高併發。

--quantization awq    # 用 AWQ(4-bit)格式載入
Code language: PHP (php)

⚠️ 超重要前提--quantization awq 不是「即時幫你壓」。它是告訴 vLLM「這個模型檔本身就是 AWQ 量化過的版本,請用 AWQ 的方式讀它」。你載入的模型名稱必須是量化版,例如 Qwen/Qwen2.5-7B-Instruct-AWQ,不是原版。這是新手第一號大坑(紅旗區細講)。

取捨表:省什麼、賠什麼

格式 精度 顯存 適合場景 代價
不量化(FP16/BF16) 最高 最吃 精度敏感、顯存夠 併發受限於顯存
FP8 高(幾乎無損) 省約一半 新卡(H100/Ada)追吞吐 需硬體支援 FP8
AWQ(4-bit) 中高 省很多 顯存吃緊、要衝併發 精度略降、需 AWQ 版模型
GPTQ(4-bit) 中高 省很多 同上,社群模型多 同上

什麼時候「值得」量化

  • 值得:模型塞不進你的卡、或想在同一張卡上服務更多併發(KV Cache 有更多空間)。
  • 值得:你的任務對一兩分精度不敏感(聊天、摘要、客服)。
  • 🤔 再想想:數學、程式碼生成、需要嚴謹推理——先用小樣本比對量化前後的答案品質再決定。
  • 別為省而省:顯存明明夠,硬上 4-bit 反而白白損失精度,吞吐提升也有限。

📌 知道就好:FP8 通常是 H100 / L40S 這類新卡才吃得動;AWQ/GPTQ 是社群最常見、老卡也能跑的 4-bit 方案。你不用背細節,記得「量化 = 省顯存換一點精度」就抓得住方向。


壓測:用數字說話,別靠感覺

調參最忌諱「感覺好像變快了」。vLLM 內建了壓測工具,讓你用真實數字判斷。

概念:三個你一定要看懂的指標

TTFT  (Time To First Token)  第一個字吐出來要多久 → 使用者「等待感」
TPOT  (Time Per Output Token) 每個後續 token 間隔 → 打字「流暢感」
Throughput (tokens/sec)       整台機每秒總產出 → 你的「產能」

一句話記法:

  • TTFT 高 = 使用者盯著空白畫面乾等(prefill 階段慢或排隊)。
  • TPOT 高 = 字一個一個慢慢蹦(decode 階段慢,或批次太滿在搶資源)。
  • Throughput 低 = 花同樣的錢服務的人變少(沒喂飽 GPU)。

怎麼跑(概念版)

新版 vLLM 提供 vllm bench 子指令;舊一點的版本是 benchmark_serving.py 腳本。你不用背參數,重點是看懂它在做什麼:

# 先在一個終端把 server 跑起來(第 1 篇教過)
vllm serve Qwen/Qwen2.5-7B-Instruct --max-num-seqs 256

# 另一個終端打壓測:模擬多個併發請求打進去
vllm bench serve \
  --model Qwen/Qwen2.5-7B-Instruct \
  --num-prompts 500 \
  --request-rate 20
Code language: PHP (php)

這在幹嘛:模擬「500 個請求、每秒約 20 個」灌進你的 server,跑完印出一張報告:平均 TTFT、TPOT、以及整體 throughput。

看懂報告,決定往哪調

拿到數字後的決策邏輯(這才是重點):

觀察到的現象 可能原因 調的方向
Throughput 低、GPU 使用率沒滿 批次喂不飽 調高 --max-num-batched-tokens / --max-num-seqs
TTFT 隨併發暴增 請求在排隊 加卡(TP)或量化騰出 KV Cache 空間
高併發時 OOM / 請求被拒 顯存不夠塞 KV Cache 量化、或調高 --gpu-memory-utilization(第 2 篇)
TPOT 偏高但吞吐也高 批次太滿,個別請求被稀釋 調低 --max-num-seqs 換低延遲

🎯 心法:一次只動一個參數,重跑壓測比較。同時改三個,你永遠不知道是哪個起的作用——這跟你叫 AI 一次改一個檔案再驗收,是同一個道理。


🚩 實戰紅旗:AI 生的指令最常見的坑

AI 給你的 vllm serve 指令看起來永遠很專業,以下四個是它最常出包、而你一眼就能抓的地方。

🚩 紅旗 1:TP 數不等於你的 GPU 張數

# AI 抄了別人 4 卡的指令,貼到你 2 卡的機器
vllm serve some-70b-model --tensor-parallel-size 4   # 🚩 你只有 2 張卡
Code language: PHP (php)

症狀:啟動就報錯,類似 RuntimeError: ... world_size ... available devices 2怎麼跟 AI 說:「我這台只有 2 張 GPU,把 tensor-parallel-size 改成符合我的硬體」。 額外檢查:TP 數還要能整除模型的 attention head 數(通常 2、4、8 這種很安全)。設 3 這種怪數字要警覺。

🚩 紅旗 2:--quantization awq 卻載入原版模型

# 🚩 模型是原版 FP16,卻叫 vLLM 用 awq 讀它
vllm serve Qwen/Qwen2.5-7B-Instruct --quantization awq
Code language: PHP (php)

症狀:載入失敗,或報「找不到量化權重 / quant config」。 根因--quantization awq 是「用 AWQ 方式讀一個已經是 AWQ 的模型」,不是即時壓縮。 怎麼跟 AI 說:「要嘛換成量化版模型名稱(例如 -AWQ 結尾那個),要嘛拿掉 --quantization」。

🚩 紅旗 3:--max-num-batched-tokens 設太小,吞吐上不去

vllm serve my-model --max-num-batched-tokens 512   # 🚩 太小了
Code language: PHP (php)

症狀:壓測時 GPU 使用率上不去、throughput 卡在低點,但沒有報錯(最陰險,因為「看起來能跑」)。 根因:每個 step 只能處理 512 token,長 prompt 進來連一個都塞不滿,GPU 大量閒置。 怎麼跟 AI 說:「吞吐偏低但 GPU 沒滿,幫我把 max-num-batched-tokens 調大(例如 8192 或更高)再壓測比較」。

🚩 紅旗 4:量化省下的顯存沒拿去用

量化把權重壓小後,多出來的顯存應該讓 KV Cache 吃掉、服務更多併發。如果 AI 量化了卻沒動 --max-num-seqs,等於省了錢沒花出去。

怎麼跟 AI 說:「我已經量化省了顯存,順便把併發上限(max-num-seqs)往上調,把空間用起來」。

🚩 紅旗 5:只憑一次結果就下結論

「我把 max-num-seqs 從 128 調到 256,感覺快多了」   # 🚩 沒有數據、沒有對照
Code language: PHP (php)

沒有壓測數字、沒有固定其他變因,這種結論不可信。要有 before/after 的 TTFT / throughput 才算數。


Vibe Coder 驗收檢查點

拿到 AI 的調校方案時,逐項確認(做得到的動作):

  1. 對硬體--tensor-parallel-size 的數字 = 你機器實際 GPU 張數嗎?
    • 動作:跑 nvidia-smi -L 看有幾張卡,數字要對得上。
  2. 對模型:有 --quantization 時,模型名稱是量化版嗎(通常帶 AWQ/GPTQ/FP8 字樣)?
  3. 能起來:server 啟動 log 有沒有印出類似 Application startup complete / 監聽埠號,而不是 traceback?
    • 動作:看啟動輸出最後幾行,卡在 error 就是沒起來。
  4. 有數據:調參前後都有跑 vllm bench(或等價壓測),拿得出 TTFT / throughput 的 before/after 嗎?
  5. 一次一變數:這次調整只動了一個參數嗎?(多個一起動 → 要求分開驗證)

只要有一項打叉,就把它貼回去問 AI,別急著收。


看不懂就這樣問 AI

把指令或壓測報告直接貼給 AI,套用這些提問句:

「用白話解釋這串 vllm serve 參數每一個在幹嘛,我要判斷適不適合我的硬體。我有 __ 張 __ 顯卡。」

「這是我的 vllm bench 壓測報告(貼上),throughput 偏低但 GPU 使用率沒滿,最可能是哪個參數要調?一次只給我一個建議。」

「我想在同一張卡上服務更多併發,量化(AWQ/GPTQ/FP8)哪種適合我這張卡?各自的精度代價是什麼?」

「幫我檢查:這個 –quantization 設定跟我載入的模型名稱是相容的嗎?」


本篇小結

  • continuous batching 是 vLLM 高吞吐的引擎,自動運作,你只要餵對參數把它喂飽。
  • 五個核心旋鈕:--tensor-parallel-size(幾張卡跑一個模型)、--max-num-seqs(幾個人上車)、--max-num-batched-tokens(一批總工作量)、--quantization(壓權重換顯存)、--dtype(放 auto 就好)。
  • 量化 = 省顯存/提併發 換一點精度;顯存吃緊或要衝併發才值得,精度敏感任務先小樣本驗證。
  • 調參靠數據:看 TTFT / TPOT / throughput 三個指標,一次動一個參數重壓測。
  • 認得 5 個紅旗:TP 對不上卡數、量化格式對不上模型、batched-tokens 太小、省了顯存沒用、沒數據就下結論。

下一篇(#04,系列最終篇)會把這些串起來,談上線後的穩定性與監控——當半夜請求量爆了,你怎麼從指標看出是撞到哪個上限。

進階測驗:vLLM 榨乾吞吐量

測驗目標:驗證你是否能在實際情境中應用所學。
共 5 題,包含情境題與錯誤診斷題。

1. 你的服務常收到「一堆長 prompt(各約 4000 token)」湧入,發現吞吐上不去、GPU 卻沒滿載。目前設定是 --max-num-seqs 256 --max-num-batched-tokens 8192。最該先動的是? 情境題

–max-num-seqs 256 # 併發上限(幾個人上車) –max-num-batched-tokens 8192 # 一批總 token 量(8192 / 4000 ≈ 2)
  • A. 把 max-num-seqs 調到 512,讓更多人上車
  • B. 調高 max-num-batched-tokens,因為 token 上限先卡住、每批只塞得下約 2 個長請求
  • C. 加上 –quantization awq 就會自動變快
  • D. 把 tensor-parallel-size 調成 1

2. 你要在同一張卡上服務更多併發使用者,決定改用量化模型。以下哪個做法最正確? 情境題

  • A. 保持原版模型,只加上 –quantization awq 即可
  • B. 換量化版模型後,維持原本的 max-num-seqs 不動
  • C. 換成量化版模型(名稱帶 AWQ),並把省下的顯存拿去調高 max-num-seqs
  • D. 顯存明明夠也硬上 4-bit,反正越省越好

3. 你要驗收 AI 的調校方案,且需要「有數據」才能收。下列哪個做法最符合文章心法? 情境題

  • A. 同時調 max-num-seqs、batched-tokens、量化三項,一次到位
  • B. 憑手動打幾句話「感覺變快了」就收
  • C. 只看 server 有沒有啟動成功就算通過
  • D. 一次只動一個參數,用 vllm bench 跑出 before/after 的 TTFT 與 throughput 比較

4. AI 給你這串指令,貼到你只有 2 張 GPU 的機器上跑,啟動就報錯。最可能的原因是? 錯誤診斷

$ vllm serve some-70b-model –tensor-parallel-size 4 RuntimeError: … world_size … available devices 2
  • A. 模型檔案損毀,需要重新下載
  • B. tensor-parallel-size 設 4 但機器只有 2 張卡,TP 數對不上實際 GPU 張數
  • C. 忘記加 –quantization 參數
  • D. max-num-batched-tokens 設太小

5. 下面這串指令載入失敗,報「找不到量化權重 / quant config」。問題出在哪? 錯誤診斷

$ vllm serve Qwen/Qwen2.5-7B-Instruct –quantization awq # 錯誤:找不到量化權重 / quant config
  • A. –quantization 應該寫成 gptq 才對
  • B. 顯存不足,需要調高 –gpu-memory-utilization
  • C. 載入的是原版 FP16 模型,卻叫 vLLM 用 AWQ 讀它;應換成 AWQ 量化版模型或拿掉 –quantization
  • D. tensor-parallel-size 沒設定

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *