Agentic Research
首頁/工具/vLLM 部署與效能調優完整指南

vLLM 部署與效能調優完整指南

2026/05/107 分鐘Bryan Chan最後更新 2026/05/10
這篇屬於工具主題Inference

先讀這些

這篇文章在學習路徑上假設你已經讀過下列內容。

vLLM 是什麼?

vLLM 是目前最快的開源 LLM 推理引擎之一,核心創新是 PagedAttention,類似作業系統的虛擬記憶體管理,大幅減少 KV Cache 浪費。

  • 吞吐量:比 HuggingFace Transformers 快 24 倍
  • 並發:支援高並發請求
  • OpenAI 兼容 API:無縫遷移

安裝

pip install vllm

部署模型

# 啟動 OpenAI 兼容 Server
vllm serve Qwen/Qwen2.5-7B-Instruct --port 8000

# 量化部署(減少記憶體)
vllm serve Qwen/Qwen2.5-7B-Instruct --quantization awq --port 8000

# 指定 GPU 記憶體
vllm serve Qwen/Qwen2.5-7B-Instruct --gpu-memory-utilization 0.9

在 Claude Code 中使用

{
  "apiKey": "not-needed",
  "baseURL": "http://localhost:8000/v1",
  "model": "Qwen/Qwen2.5-7B-Instruct"
}

效能調優

參數建議值說明
--max-model-len8192最大上下文長度
--gpu-memory-utilization0.9GPU 記憶體利用率
--tensor-parallel-sizeGPU 數量多 GPU 張量並行

PagedAttention 與 KV Cache 的取捨

KV 快取:為什麼讀懂問題與生成回答是兩種成本五個步驟解釋 KV 快取。Prefill 階段一次讀完你的全部輸入,每個輸入 token 算出一組 K/V(可以理解成「這個 token 要被怎麼看」的摘要),然後被存進快取 —— 存下來之後就不用再算。Decode 階段一次生成一個 token,每個新 token 都需要「看」前面所有 token,但那些全部直接從快取讀取、不重算,只算新的這一個;而每生成一個 token 又把它自己的 K/V 加進快取,所以快取隨回答變長而成長。代價是初學者真正會撞到的:快取佔的是記憶體而不是算力,而且隨上下文長度線性成長,所以長對話不只是貴、還會變慢 —— 而這與「模型變笨」是兩個獨立的原因,雖然它們常常同時發生。三個實務推論:首字時間與每秒字數量的是不同階段,所以一個正常另一個可能很差;開新對話能同時改善成本、速度與品質,因為三者都回溯到同一個不斷成長的快取;更長的上下文視窗提高了裝得下多少的上限,但不會讓長上下文變便宜。「讀懂你的問題」與「寫出回答」是兩種不同的成本PREFILL —— 一次讀完全部輸入貓坐在KV 快取(佔記憶體,隨長度成長)DECODE —— 一次一個 token墊子上你的輸入被一次讀完(prefill)。每一個輸入 token 都算出一組 K/V—— 可以理解成「這個 token 要被怎麼看」的摘要。為什麼這值得知道· 首字時間(TTFT)與每秒字數量的是不同階段,所以一個看起來正常、另一個可能很差。· 開新對話能同時改善成本、速度與品質 —— 因為三者都回溯到同一個不斷成長的快取。· 更長的上下文視窗提高了「裝得下多少」的上限,它不會讓長上下文變便宜。1
1/5Prefill:一次讀完輸入
每個輸入 token 算出一組 K/V
第 1 步,共 5 步 Prefill:一次讀完輸入
圖:KV cache 在 prefill 與 decode 兩個階段的作用。為什麼它決定吞吐量,以及它為什麼吃記憶體。

理解 KV Cache 的記憶體行為,是調優的前提。生成過程中,每個請求都要為已處理的 token 保留鍵值快取,長上下文與高並發會把這塊記憶體迅速吃光。早期做法為每個請求預留一整段連續空間,造成大量內部碎片;PagedAttention 把快取切成固定大小的區塊,按需分配,用多少給多少,因此能用更少記憶體容納更多並發請求。

區塊大小(block size):區塊越小,碎片越少但管理開銷越高;區塊越大,管理簡單但尾端浪費增加。多數情況用預設值即可,除非在特定工作負載下觀察到明顯的記憶體浪費。

前綴快取(prefix caching):若大量請求共用相同的開頭(例如同一段系統提示或同一份長文件),開啟前綴快取可以避免重複計算,直接複用已算好的快取區塊,對吞吐有明顯幫助。代價是需要額外管理快取的生命週期與淘汰。

分塊預填充(chunked prefill):把長提示的預填充拆成多段執行,讓生成與預填充交錯,能降低長提示對其他請求的阻塞,改善整體延遲分佈。但拆得越細,單次計算效率略降,需要在吞吐與延遲之間取捨。

量化:AWQ 或 GPTQ 等量化能顯著降低權重佔用的記憶體,換取部分精度。原則是先確認輸出品質可接受,再談省下的記憶體能換多少並發。


部署參數的實務調整

參數調整方向取捨
--max-model-len依實際需求設定,不要一次開到最大開太大會預留過多 KV Cache 空間
--gpu-memory-utilization依顯卡與同機其他程序調整太高有機會被其他程序搶佔而失敗
--tensor-parallel-size設為實際使用的 GPU 數量設錯無法啟動或效率下降
--max-num-seqs依延遲目標調整並發上限越高吞吐越好但單請求延遲上升
--dtype依硬體支援選擇精度與速度的平衡
量化選項記憶體不足時考慮精度可能下降

實務流程是先把模型跑起來確認可服務,再逐步加壓找出穩定上限。--gpu-memory-utilization 不是越高越好:同一台機器上若有其他程序(例如另一個服務或監控工具)需要顯存,留一點餘量能避免啟動或執行中途失敗。多 GPU 部署時,--tensor-parallel-size 必須與實際可見的 GPU 數量一致,並確認機器內 GPU 之間的連線頻寬足夠,否則張量並行的收益會被打折。


效能基準測試方法

沒有量測就沒有調優。以下做法能讓比較結果可信。

  • 固定輸入長度與輸出長度,避免每次測試條件不同。
  • 先做暖機,等模型載入與快取穩定後再開始計時。
  • 做併發掃描:從單請求逐步提高同時請求數,觀察吞吐與延遲如何變化。
  • 分別量測首 token 延遲(等待時間)與每 token 生成時間,兩者對體驗的影響不同。
  • 記錄吞吐(每秒處理的 token 數)與延遲的分位數,不要只看平均值,平均值會掩蓋長尾。
  • 每次只改一個參數,並保留原始數據以便回溯。
  • 注意散熱與降頻,長時間連測會讓後段數據偏低。

建議把測試腳本化並固定環境,這樣換模型、換量化或換參數時可以快速重跑並對照。若同時看吞吐與延遲,通常會看到一條取捨曲線:併發越高吞吐越高,但每個請求的等待越久,最終要依業務的可接受延遲來決定工作點。


常見錯誤與檢查清單

常見錯誤

  • 把 --max-model-len 直接開到模型上限,導致可服務的並發數大幅下降。
  • --gpu-memory-utilization 設得過高,與同機其他程序搶佔顯存而啟動失敗。
  • --tensor-parallel-size 與實際 GPU 數量不符,服務無法啟動。
  • 只看吞吐數字,忽略延遲分佈,實際使用者體驗很差。
  • 在沒有暖機的情況下比較兩組設定,結論不可靠。
  • 開了量化卻沒有重新檢查輸出品質。
  • 把 apiKey 當成必要欄位,誤以為本地服務也需要驗證才能連線。
  • 服務綁定在公開介面卻沒有任何存取控制。

檢查清單

  • 已確認模型可正常載入並回應請求。
  • 已依實際需求設定 --max-model-len。
  • 已為其他程序保留適度的顯存餘量。
  • 已確認 --tensor-parallel-size 與 GPU 數量一致。
  • 已決定是否需要開啟前綴快取。
  • 已量測首 token 延遲與每 token 生成時間。
  • 已記錄吞吐與延遲分位數,並做過併發掃描。
  • 已確認量化後的輸出品質可接受。
  • 已確認服務的網路綁定與存取控制符合預期。

推薦閱讀

在這條路徑上的下一步