很多團隊把它vLLM 當 demo 跑,但是其實這沒把它系統能力發揮出來。這篇文章將介紹怎麼讓 vLLM 真正幹活——持續輸出高令牌/秒,哪些參數真正有用,以及怎麼在延遲和成本之間做取捨。
先説 vLLM 到底好在哪
vLLM 提供 OpenAI 兼容的 API,核心是 continuous batching 加上 PagedAttention。PagedAttention 用分頁管理 KV 緩存,內存複用做得很高效,能同時跑多個序列,GPU 佔用率拉滿,還能流式輸出令牌。
並且工作流程不復雜。請求進來帶着 prompt ,調度器把它們切成微批次餵給 GPU,KV 緩存存着注意力的鍵值對,PagedAttention 按頁分配避免碎片。相似的 prompt 可以跨請求複用 KV 頁,這就是前綴緩存。並行度和內存怎麼分配由你定,這是性能調優的核心。
批處理大小
批處理越大吞吐量越高,但尾部延遲也跟着漲。得先想清楚場景:聊天類交互要的是低 TTFT(首令牌延遲),批次小點;批量任務或者 RAG 管道追求高吞吐,TTFT 長點能接受。
網關層得限制單請求的最大令牌數,不然一個大請求能把隊列堵死。多箇中等大小的 prompt 比少數巨型 prompt 效果好,continuous batching 在形狀規整時效率最高。如果能按輸出長度分類(短/中/長),就給每類跑獨立的 vLLM worker,延遲會穩定很多。
前綴緩存算是白撿的性能
兩個請求共享相同前綴時——系統提示詞、few-shot 示例、檢索的引導文本——vLLM 直接複用 KV 緩存。這是零成本加速。
怎麼設計才能吃到這個紅利?可以及逆行系統提示詞跨租户標準化,few-shot 示例保持完全一致,變量放用户輸入裏別放示例裏。RAG 場景就把模板和指令緩存起來,每個請求只追加檢索到的事實。
量化可以性能倍增器
AWQ 或 RTN 做 4-bit 權重量化,內存省了不少,perplexity也幾乎不掉,這是服務端點的默認選擇。KV 緩存也能量化,緩存佔用減少意味着能跑更多併發序列,但代價是超長生成時質量可能輕微下降。
經驗如下:GPU 內存緊張、調度器塞不下足夠多序列時就量化。更多並行序列帶來的收益通常遠超全精度權重那點質量提升。
併發參數這幾個很重要
--max-num-seqs
限制併發序列數,A100 級別的卡從 64-128 起步,往上調到 TTFT 開始變差為止。
--max-model-len
別設成模型理論最大值,除非真需要那麼長,限制小點意味着 KV 頁小,並行度高。
--tensor-parallel-size
是把大模型切到多卡,NVLink 這種快速互連是必須的,批次得夠大才能掩蓋通信開銷。
--gpu-memory-utilization
留 10-15% 餘量,應對流量尖峯時的 OOM。
千萬別把所有參數都拉滿然後指望調度器自己搞定,這個一定要實測。
容量規劃看令牌率而不是 QPS
兩個請求 QPS 一樣,令牌的預算可能天差地別。規劃容量要用輸入加輸出的令牌/秒。設 C 是選定批處理形狀下單 GPU 的持續令牌/秒,容量約等於 GPU 數量x C x 利用率。利用率保持在 70-85% 能吸收峯值,再高就該橫向擴了。
有時候 90% 的利用率會莫名其妙的慢,所以儘量不要到達這個臨界值。
生產配置
# pull a vLLM image with your preferred model
docker run --gpus all --rm -p 8000:8000 \
-v /models:/models \
vllm/server:latest \
--model /models/Qwen2.5-7B-Instruct-AWQ \
--dtype auto \
--tensor-parallel-size 1 \
--max-num-seqs 128 \
--max-model-len 4096 \
--gpu-memory-utilization 0.9 \
--enforce-eager \
--trust-remote-code false
AWQ 模型做了權重 4-bit 量化,部署密度高。
--enforce-eager
避免混合流量下漫長的 CUDA graph 預熱,流量模式統一且要 CUDA graph 優化時再關掉。
--trust-remote-code=false
在多租户環境保持安全。
OpenAI 兼容的請求寫法如下:
curl http://localhost:8000/v1/chat/completions \
-H"Content-Type: application/json" \
-d'{
"model":"Qwen2.5-7B-Instruct-AWQ",
"messages":[{"role":"user","content":"Write a haiku about GPUs"}],
"stream":true,
"max_tokens":128,
"temperature":0.3
}'
調度和公平性
工作負載如果混了短生成和長生成,跑兩個池:短任務優先池和長任務池。TTFT 保持合理範圍,批量吞吐也不損失。准入控制在網關層做,按租户限令牌速率,vLLM 專心批處理不需要管流控。背壓機制也是要有的,慢消費者會拖累流式輸出,所以一定要將服務器端超時和最大隊列長度設好。
RAG 令牌長度
7B 模型的上下文控制在 2-3k 令牌,再長注意力成本是二次方,質量提升有限。檢索後修剪也很重要,刪掉近似重複的塊,只留高分句子。靜態前導加動態事實的結構,前綴緩存命中率最高。
監控必須要有
儀表板最少得有這些:TTFT 的 p50 和 p95,令牌/秒(輸入、輸出、總計),活躍序列數和 KV 緩存利用率,批處理大小分佈隨時間變化,調度器隊列長度和准入拒絕率,OOM 和驅逐事件。
活躍序列數飽和或者 KV 緩存接近 100% 的時候 TTFT p95 飆升,説明容量到頭了,橫向擴或者減模型長度。
常見坑和方案
全局最大上下文設太大,KV 頁巨大並行度差,解決方法是設合理的
--max-model-len
,長上下文只在需要時開單獨層級。
每個租户 prompt 隨機沒法複用前綴,解決方案是標準化樣板用模板。
輸出不限制單個請求霸佔調度器,可以在端點層面限
max_tokens
。
所有流量打一個 worker,而GPU 閒置,需要在智能網關後跑多 worker 按桶分片。
儀表板只看 QPS 屬於監控的混亂,要把令牌/秒和 TTFT 提到優先級,緩存飽和加告警。
總結
vLLM 的核心價值不是 prompt 技巧,是讓 GPU 一直幹活。令牌當預算單位,前綴設計好複用,上下文窗口別亂開,併發上限設實際點,吞吐量自然上去而且不會突然垮。
https://avoid.overfit.cn/post/89022caa9a4346b290c212c0c9bbaa57
作者:Nexumo