推理實(shí)踐:KV Cache優(yōu)化與參數(shù)調(diào)優(yōu)指南)
vLLM這幾年的熱度但凡做過大模型推理落地的人都深有體會(huì)。所謂高吞吐推理引擎核心目標(biāo)就是在有限的GPU顯存里把本地高并發(fā)推理服務(wù)的單位時(shí)間請(qǐng)求處理量做到最大化。我最初被vLLM吸引就是因?yàn)橐粋€(gè)很現(xiàn)實(shí)的問題同樣的模型用普通框架部署時(shí)并發(fā)一上來就顯存爆炸、請(qǐng)求排隊(duì)換成vLLM之后吞吐直接翻了幾倍而GPU利用率終于跑到了該有的水平。這篇文章我打算圍繞vLLM在本地高并發(fā)推理服務(wù)中的落地實(shí)踐把核心原理、部署方式、參數(shù)調(diào)優(yōu)和踩坑記錄一次性講清楚。不管你是在做內(nèi)部大模型API還是在折騰個(gè)人推理服務(wù)只要被并發(fā)和顯存卡過這篇內(nèi)容應(yīng)該能直接幫你省掉不少彎路。1. 項(xiàng)目核心vLLM到底解決了什么問題1.1 傳統(tǒng)推理框架的瓶頸出在哪先聊聊我最早用原生transformers代碼部署推理時(shí)的痛苦。模型加載沒問題單條請(qǐng)求推理速度也能接受但只要并發(fā)請(qǐng)求一多整套服務(wù)就像得了腸胃炎——要么顯存溢出直接OOM要么請(qǐng)求全部卡在隊(duì)列里慢慢等。問題本質(zhì)不在計(jì)算而在KV Cache。Transformer模型在生成每個(gè)token時(shí)都要讀取歷史token的Key和Value向量這些向量存在顯存里就是KV Cache。傳統(tǒng)推理框架為了簡單通常按請(qǐng)求的最大序列長度一次性把顯存預(yù)留出來。比如一個(gè)模型最大支持4096 token的上下文那每個(gè)請(qǐng)求的KV Cache就按4096個(gè)token的體量去占顯存哪怕這個(gè)請(qǐng)求實(shí)際只生成了幾十個(gè)token預(yù)留的空間也不會(huì)釋放。我粗略算過一筆賬。一個(gè)70億參數(shù)模型假設(shè)40層、隱層維度4096FP16精度下單個(gè)token的KV Cache大約占 40 × 4096 × 2 × 2 字節(jié)也就是600多KB。如果按滿上下文4096 token預(yù)留單請(qǐng)求就要吃掉256MB顯存。32路并發(fā)同時(shí)進(jìn)來光KV Cache就是8GB。顯存被白白浪費(fèi)并發(fā)能力自然上不去。除此之外傳統(tǒng)框架的批處理方式也很粗糙。多個(gè)請(qǐng)求湊成一個(gè)batch后必須等batch里最慢的那個(gè)序列生成完整個(gè)batch才能釋放中途GPU會(huì)出現(xiàn)大量空閑氣泡。在長文本生成場景里這種浪費(fèi)尤其明顯。1.2 vLLM的三個(gè)關(guān)鍵設(shè)計(jì)vLLM針對(duì)上面兩個(gè)痛點(diǎn)做了三件核心事PagedAttention、Continuous Batching和顯存感知調(diào)度。第一PagedAttention把KV Cache分頁管理。不再為每個(gè)請(qǐng)求預(yù)占整塊連續(xù)顯存而是像操作系統(tǒng)管理內(nèi)存一樣按固定大小的塊分配用到多少分配多少。顯存碎片的利用率大幅提高同樣的顯存能容納更多并發(fā)請(qǐng)求。第二Continuous Batching實(shí)現(xiàn)了迭代級(jí)調(diào)度。傳統(tǒng)方案是請(qǐng)求級(jí)調(diào)度一個(gè)batch落地后直到所有序列結(jié)束才換下一批vLLM則在每次decode迭代之后完成的請(qǐng)求立即退出新進(jìn)來的請(qǐng)求馬上補(bǔ)位GPU永遠(yuǎn)在滿負(fù)荷工作。第三調(diào)度器會(huì)做顯存感知。每個(gè)請(qǐng)求進(jìn)來時(shí)vLLM會(huì)估算它需要的KV Cache塊數(shù)量顯存足夠就接收不夠就掛起等待而不是等到解碼中途才發(fā)現(xiàn)顯存不夠?qū)е卤罎?。這套設(shè)計(jì)讓服務(wù)在高并發(fā)下具備可預(yù)期的兜底行為。1.3 適合什么場景不適合什么場景直接說結(jié)論。vLLM最擅長的是高并發(fā)API服務(wù)、多輪對(duì)話、長上下文推理以及離線批量跑分這類場景特征是并發(fā)高、token吞吐量大、對(duì)單請(qǐng)求延遲要求不是極端苛刻。但如果你的場景是單請(qǐng)求超低延遲比如語音助手那種要求幾十毫秒內(nèi)響應(yīng)的實(shí)時(shí)交互vLLM未必比專門優(yōu)化過的低延遲方案更合適。另外如果你需要對(duì)解碼過程做大量自定義算子改動(dòng)或者要接入某些特殊的采樣邏輯vLLM的調(diào)度框架反而會(huì)帶來限制。選型時(shí)先看業(yè)務(wù)形態(tài)別盲目追新。2. 核心原理PagedAttention與連續(xù)批處理2.1 PagedAttention給KV Cache做“虛擬內(nèi)存”PagedAttention是vLLM最核心的設(shè)計(jì)理解它就理解了vLLM的一大半。傳統(tǒng)顯存管理可以類比成訂酒店為了讓客戶住得舒服直接包下一整層樓不管客戶實(shí)際住幾間。請(qǐng)求數(shù)量一多樓層不夠用后面的客戶只能在樓下排隊(duì)。PagedAttention的做法變成了按房間按天訂客戶住幾天就訂幾間房間分布在樓層不同位置也沒關(guān)系只需要記錄房間號(hào)就行。具體到實(shí)現(xiàn)vLLM把KV Cache劃分成固定大小的邏輯塊默認(rèn)每個(gè)塊可以存16個(gè)token的KV向量。每個(gè)請(qǐng)求有一個(gè)邏輯塊表記錄它當(dāng)前占用哪些物理塊。當(dāng)請(qǐng)求生成了新的token就往表里追加對(duì)應(yīng)的物理塊如果物理塊不夠了調(diào)度器會(huì)先分配新的塊分配不到就暫停請(qǐng)求。這里有個(gè)關(guān)鍵收益因?yàn)閴K是等大小的顯存中幾乎不存在碎片問題。一塊內(nèi)存不管屬于哪個(gè)請(qǐng)求只要沒被用上就能立刻分配給其他請(qǐng)求。傳統(tǒng)方案中預(yù)留后不可復(fù)用的情況徹底消失了。2.2 Continuous Batching迭代級(jí)調(diào)度讓GPU一直“滿座”再講Continuous Batching。vLLM對(duì)批次的處理粒度非常細(xì)調(diào)度發(fā)生在每一次decode迭代之后。比如當(dāng)前batch里有8個(gè)請(qǐng)求在生成其中3個(gè)已經(jīng)生成到結(jié)束標(biāo)記它們立刻退出騰出的顯存塊馬上可以被新進(jìn)入的請(qǐng)求使用。這和傳統(tǒng)batching的差別非常大。傳統(tǒng)batching是短板效應(yīng)batch里有一個(gè)請(qǐng)求要生成500個(gè)token其他幾個(gè)只要50個(gè)GPU也得陪著跑完500步。vLLM則讓短請(qǐng)求提前下車新請(qǐng)求隨時(shí)上車GPU在每一輪迭代都處于相對(duì)滿負(fù)荷的狀態(tài)。我自己的體會(huì)是這個(gè)機(jī)制對(duì)混合負(fù)載尤其有效。實(shí)際業(yè)務(wù)里請(qǐng)求長度參差不齊有的問一句就結(jié)束有的要生成一大段代碼。Continuous Batching能把長短請(qǐng)求混在一起調(diào)度互不拖累GPU平均利用率能上一個(gè)臺(tái)階。2.3 為什么整體提升能到幾十倍很多人看到公開benchmark里vLLM吞吐提升5倍、10倍甚至20倍的數(shù)字覺得夸張。其實(shí)這些數(shù)字不是玄學(xué)而是幾個(gè)因素疊加的結(jié)果。第一顯存利用率提高直接轉(zhuǎn)化為更大的并發(fā)批大小。以前只能并發(fā)4路請(qǐng)求現(xiàn)在能并發(fā)16路吞吐自然漲。第二decode階段的batch更大GPU矩陣運(yùn)算的并行效率更高。第三PagedAttention對(duì)prefill階段也有優(yōu)化超長prompt可以按塊切分處理首token時(shí)間有所改善。我實(shí)測過的效果是在顯存受限的高并發(fā)場景提升幅度最明顯三四倍是保底如果你的請(qǐng)求普遍很長、上下文很大那收益會(huì)更夸張接近公開數(shù)據(jù)里的上限。反過來短請(qǐng)求、低并發(fā)、算力本來就閑的場景提升幅度沒那么大。所以判斷收益前先看清自己的負(fù)載特征。3. 本地部署實(shí)操從安裝到啟動(dòng)服務(wù)3.1 環(huán)境準(zhǔn)備與安裝部署vLLM之前先確認(rèn)三件事GPU型號(hào)和顯存、GPU驅(qū)動(dòng)版本、Python環(huán)境。我的建議是至少8GB顯存起步否則很多主流開源模型放進(jìn)去之后剩下的顯存連KV Cache都擠不出多少并發(fā)根本沒戲。Python版本建議3.9到3.12之間。CUDA方面vLLM打包的預(yù)編譯版本通常對(duì)應(yīng)CUDA 11.8或12.1你本地的GPU驅(qū)動(dòng)需要支持對(duì)應(yīng)的CUDA版本。安裝時(shí)最省心的方式就是用官方軟件倉庫直接裝pip install vllm裝完驗(yàn)證一下版本python -c import vllm; print(vllm.__version__)如果網(wǎng)絡(luò)受限配置國內(nèi)鏡像源pip install vllm -i https://pypi.tuna.tsinghua.edu.cn/simple這里有個(gè)坑如果你的機(jī)器上之前裝過舊版vLLM或者一堆深度學(xué)習(xí)的依賴包建議先建一個(gè)干凈的虛擬環(huán)境再裝。vLLM對(duì)torch、transformers的版本要求比較嚴(yán)格混裝容易出現(xiàn)各種莫名其妙的沖突。我在內(nèi)網(wǎng)機(jī)器上踩過不少次最后統(tǒng)一用虛擬環(huán)境隔離才穩(wěn)定下來。3.2 啟動(dòng)服務(wù)核心參數(shù)逐個(gè)講vLLM裝好之后啟動(dòng)推理服務(wù)的方式很簡潔。官方入口是vllm serve命令直接指定模型路徑或模型名它就會(huì)拉起一個(gè)OpenAI兼容的HTTP服務(wù)。我常用的一條啟動(dòng)命令是vllm serve Qwen/Qwen2.5-7B-Instruct \ --host 0.0.0.0 \ --port 8000 \ --gpu-memory-utilization 0.92 \ --max-model-len 8192 \ --max-num-seqs 128 \ --tensor-parallel-size 1 \ --enable-prefix-caching這些參數(shù)每一個(gè)都影響并發(fā)能力挨個(gè)說清楚--gpu-memory-utilization控制KV Cache最多占用多少比例的GPU顯存。我通常設(shè)0.85到0.95之間不建議拉滿到0.99因?yàn)镃UDA context、計(jì)算圖、激活值也要占顯存拉滿容易在運(yùn)行時(shí)碰壁。--max-model-len是支持的最大上下文長度包括輸入加輸出。它會(huì)影響KV Cache塊的分配策略和prefill的切分方式。不是越大越好得按業(yè)務(wù)實(shí)際需求來盲目設(shè)32K會(huì)讓單請(qǐng)求占用顯存大幅上升壓縮并發(fā)空間。--max-num-seqs是單個(gè)批次最多容納的序列數(shù)直接決定并發(fā)上限。設(shè)太小請(qǐng)求來了只能排隊(duì)設(shè)太大batch過大后每個(gè)序列的解碼速度會(huì)下降。初始建議64或128后續(xù)通過壓測再微調(diào)。--tensor-parallel-size是多卡并行參數(shù)。當(dāng)單卡放不下模型時(shí)設(shè)為2或4vLLM會(huì)通過Tensor Parallel把模型切到多張卡上。--enable-prefix-caching開啟前綴緩存多個(gè)請(qǐng)求共用相同prompt前綴時(shí)可以復(fù)用KV Cache多輪對(duì)話場景收益很大。3.3 調(diào)用接口與本機(jī)驗(yàn)證服務(wù)啟動(dòng)后先驗(yàn)證是否健康curl http://127.0.0.1:8000/v1/models這個(gè)接口會(huì)返回當(dāng)前加載的模型信息能通就說明服務(wù)起來了。vLLM提供了OpenAI兼容的接口格式意味著業(yè)務(wù)側(cè)可以用標(biāo)準(zhǔn)的SDK直接調(diào)用幾乎零成本切換。之前我在內(nèi)部項(xiàng)目里接多個(gè)推理框架業(yè)務(wù)代碼完全不用改只換了base_url就把vLLM接入進(jìn)去了。調(diào)用示例from openai import OpenAI client OpenAI( base_urlhttp://127.0.0.1:8000/v1, api_keylocal, ) resp client.chat.completions.create( modelQwen/Qwen2.5-7B-Instruct, messages[{role: user, content: 用一句話解釋什么是KV Cache}], max_tokens256, temperature0.7, ) print(resp.choices[0].message.content)流式輸出也是一樣的用法只需要加streamTrue。vLLM對(duì)流式場景的優(yōu)化也做得不錯(cuò)迭代級(jí)的Continuous Batching在流式輸出下更能體現(xiàn)吞吐優(yōu)勢(shì)。4. 高并發(fā)實(shí)戰(zhàn)吞吐量分析與參數(shù)調(diào)優(yōu)4.1 壓測腳本與關(guān)鍵指標(biāo)啟動(dòng)服務(wù)之后不能憑感覺判斷性能一定要做壓測。我用過最簡單的并發(fā)壓測腳本基于httpx的異步客戶端可以模擬不同并發(fā)度下的壓力。核心代碼如下import asyncio import time import statistics import httpx URL http://127.0.0.1:8000/v1/chat/completions MODEL Qwen/Qwen2.5-7B-Instruct async def send_one(client, payload, semaphore): async with semaphore: start time.time() resp await client.post(URL, jsonpayload) resp.raise_for_status() data resp.json() ttft data.get(timings, {}).get(first_token_time, None) return time.time() - start, ttft async def run_load(concurrency, total_requests, payload, semaphore): async with httpx.AsyncClient(timeout300) as client: tasks [] for _ in range(total_requests): tasks.append(send_one(client, payload, semaphore)) results await asyncio.gather(*tasks) return results if __name__ __main__: payload { model: MODEL, messages: [{role: user, content: 寫一個(gè)200字的自我介紹}], max_tokens: 256, temperature: 0.7, } for concurrency in [8, 16, 32, 64, 128]: semaphore asyncio.Semaphore(concurrency) results asyncio.run(run_load(concurrency, 200, payload, semaphore)) latencies [r[0] for r in results] tps len(results) / (sum(latencies) / concurrency) avg_latency statistics.mean(latencies) print(fconcurrency{concurrency}, TPS{tps:.2f}, avg_latency{avg_latency:.2f}s)這里的TPS計(jì)算方式比較簡單準(zhǔn)確的壓測應(yīng)該統(tǒng)計(jì)從開始到所有請(qǐng)求完成的完整窗口而不是用平均延遲除以并發(fā)數(shù)。建議在實(shí)際壓測時(shí)用固定時(shí)間窗口來統(tǒng)計(jì)完成的請(qǐng)求數(shù)。需要重點(diǎn)關(guān)注的指標(biāo)有三個(gè)TTFT也就是首Token時(shí)間。它反映排隊(duì)和prefill的開銷多輪對(duì)話場景下這個(gè)指標(biāo)尤其重要。如果TTFT飆升說明請(qǐng)求在調(diào)度器里排隊(duì)太久了。TPOT也就是每個(gè)Token的生成耗時(shí)反映decode階段的batch負(fù)載。如果TPOT從20ms漲到100ms說明一個(gè)batch里塞了太多序列每個(gè)序列分到的算力被稀釋了。TPS和整體吞吐單位時(shí)間完成的請(qǐng)求數(shù)或生成的token總數(shù)。這兩個(gè)指標(biāo)是最終的性能標(biāo)尺所有調(diào)優(yōu)最后都要落到它們上面。4.2 調(diào)優(yōu)經(jīng)驗(yàn)從吞吐曲線找最佳值我之前在單張80GB顯存的顯卡上測試過一套70億參數(shù)的模型把并發(fā)數(shù)從8一路加到256TPS的變化趨勢(shì)讓我印象很深。在低并發(fā)區(qū)間TPS基本線性增長到達(dá)某個(gè)拐點(diǎn)后增速放緩繼續(xù)加壓TPS不再增加反而平均延遲明顯惡化。這個(gè)拐點(diǎn)附近就是這臺(tái)機(jī)器的合理并發(fā)上限。針對(duì)不同負(fù)載特征調(diào)優(yōu)優(yōu)先級(jí)不一樣。短輸出場景比如分類、抽取、關(guān)鍵詞生成輸出token數(shù)少瓶頸往往是prefill。優(yōu)先調(diào)大--max-num-seqs把更多請(qǐng)求塞進(jìn)一個(gè)有prefill能力的batch同時(shí)開啟--enable-prefix-caching。這類場景里--max-model-len不用設(shè)太大反而應(yīng)該壓到能覆蓋業(yè)務(wù)輸入上限即可省下的顯存全給KV Cache。長輸出場景比如生成文章、代碼、報(bào)告decode是主要耗時(shí)每個(gè)序列長期占著顯存塊。這時(shí)優(yōu)先保證單序列的decode速度--max-num-seqs不宜無限放大否則TPOT惡化用戶體感會(huì)明顯變差。最佳做法是壓測不同并發(fā)下的TPOT曲線找到一個(gè)“TPS還在漲、TPOT還能接受”的平衡點(diǎn)。--gpu-memory-utilization的調(diào)優(yōu)也講究策略。我一般先設(shè)0.90跑一輪壓測確認(rèn)不OOM后再適當(dāng)往0.95試。如果業(yè)務(wù)高峰期請(qǐng)求排隊(duì)嚴(yán)重而是KV Cache不夠?qū)е碌目梢哉{(diào)大這個(gè)值。前提是留出足夠余量給其他顯存開銷我見過有人設(shè)0.99然后運(yùn)行中崩潰的。4.3 多卡并行與量化方案單卡放不下模型或者想進(jìn)一步擴(kuò)大并發(fā)時(shí)兩個(gè)方向可以參考。多卡方面--tensor-parallel-size 2或4vLLM會(huì)把模型權(quán)重和計(jì)算切到多張卡上。注意顯存帶寬成為新的瓶頸跨卡通信有開銷不是卡越多越快4卡以上的收益增長會(huì)明顯放緩。有條件的話建議優(yōu)先用NVLink互聯(lián)的卡效果更好。量化方面對(duì)這個(gè)場景幫助很大。70億參數(shù)的模型FP16權(quán)重要14GB顯存用AWQ或GPTQ量化為4bit后只剩約4GB剩下的顯存幾乎全給KV Cache并發(fā)能力可以翻不少。量化方式不影響OpenAI接口模型推理照常走。我自己的實(shí)測是4bit量化在對(duì)話類任務(wù)上質(zhì)量損耗不大但吞吐收益很實(shí)在。量化模型啟動(dòng)方式和普通模型一致vllm serve ./models/coder-7b-awq \ --quantization awq \ --gpu-memory-utilization 0.92 \ --max-num-seqs 128有一點(diǎn)要留意量化模型如果本身是手工轉(zhuǎn)化或社區(qū)版本精度差異可能不小上線前一定要跑一批評(píng)測集做對(duì)比不能只看指標(biāo)好看就切過去。5. 常見問題與排查實(shí)錄5.1 顯存不足與KV Cache耗盡最典型的錯(cuò)誤是啟動(dòng)或運(yùn)行時(shí)報(bào) “No available memory for the cache blocks”。這表示KV Cache的可用塊已經(jīng)被占滿了。遇到這個(gè)問題排查順序我一般是這樣第一把--max-num-seqs調(diào)小觀察是否恢復(fù)。第二把--gpu-memory-utilization從0.95降到0.85附近給其他開銷留出空間。第三檢查--max-model-len是否設(shè)得過大如果業(yè)務(wù)并不需要32K上下文壓到8K或4K能釋放大量KV Cache。最后一個(gè)隱藏點(diǎn)如果你開啟了多卡Tensor Parallel每張卡上還要額外留一部分顯存給通信緩沖這時(shí)顯存利用率更不該拉滿。5.2 首Token時(shí)間高企與請(qǐng)求排隊(duì)如果壓測時(shí)TPS不高但TTFT持續(xù)走高大概率是請(qǐng)求在調(diào)度器里排隊(duì)而不是生成太慢。通過vLLM日志里的running和waiting數(shù)量可以確認(rèn)如果waiting一直很高說明--max-num-seqs限制了并發(fā)窗口。先說結(jié)論優(yōu)先調(diào)大--max-num-seqs。如果已經(jīng)是256還排隊(duì)那就是算力或顯存真的飽和了這時(shí)候可以開--enable-prefix-caching減少重復(fù)prefill或者上多卡和量化。記住一個(gè)判斷技巧TPS上不去但TTFT高是排隊(duì)問題TPS在漲但TPOT明顯變差是batch內(nèi)過度競爭兩個(gè)問題的解決方向完全不同。5.3 依賴與版本兼容問題vLLM對(duì)底層依賴的要求出了名的嚴(yán)格。我遇到過幾次很典型的問題。一個(gè)是啟動(dòng)時(shí)提示CUDA不可用報(bào)錯(cuò)類似“Torch is not compiled with CUDA enabled”。這通常是因?yàn)榄h(huán)境里裝了一個(gè)CPU版或CUDA版本不匹配的torch。解決辦法很直接把當(dāng)前環(huán)境清理干凈重新安裝一份與vLLM匹配的torch和CUDA版本。一個(gè)是FlashAttention相關(guān)的報(bào)錯(cuò)。vLLM在許多GPU上依賴FlashAttention加速而FlashAttention對(duì)GPU架構(gòu)和CUDA版本非常敏感。如果啟動(dòng)時(shí)崩潰在FlashAttention初始化優(yōu)先考慮升級(jí)GPU驅(qū)動(dòng)、更換CUDA版本或者安裝vLLM預(yù)編譯版本。不建議自己編譯編譯時(shí)間很長而且不同硬件平臺(tái)差異很大。還有一個(gè)通用建議不要輕易把vLLM和相關(guān)依賴一起批量升級(jí)。vLLM的小版本更新經(jīng)常附帶底層算子變更升級(jí)前仔細(xì)讀更新說明并且在測試環(huán)境跑一遍回歸再動(dòng)生產(chǎn)。5.4 問題速查表問題現(xiàn)象可能原因解決辦法啟動(dòng)報(bào) No available memory for cache blocksKV Cache占用已滿降低 max-num-seqs、降低 gpu-memory-utilization、縮小 max-model-lenTTFT高但TPS不高請(qǐng)求在排隊(duì)調(diào)大 max-num-seqs、開啟 prefix-cachingTPOT明顯變差batch內(nèi)序列數(shù)過多適當(dāng)減小 max-num-seqs平衡吞吐與單請(qǐng)求速度報(bào) Torch CUDA 相關(guān)錯(cuò)誤torch 與 CUDA 版本不匹配重建虛擬環(huán)境重裝匹配版本的 torch 和 vLLMFlashAttention 初始化崩潰GPU架構(gòu)或 CUDA 版本不兼容升級(jí)驅(qū)動(dòng)、更換 CUDA 版本或用預(yù)編譯安裝包多卡啟動(dòng)報(bào) NCCL 錯(cuò)誤多卡通信異常檢查顯卡互聯(lián)方式、驅(qū)動(dòng)版本降低 tensor-parallel-size 測試量化模型輸出質(zhì)量下降量化精度損失或校驗(yàn)集不足換用不同量化位寬先跑評(píng)測對(duì)比再上線寫在最后的一點(diǎn)經(jīng)驗(yàn)整個(gè)項(xiàng)目折騰下來我最深的體會(huì)是vLLM的收益上限取決于你的負(fù)載特征而不是參數(shù)本身。抄網(wǎng)上的配置沒有任何意義必須自己壓測、畫曲線、找拐點(diǎn)。啟動(dòng)服務(wù)一句vllm serve就能跑起來但真正把它調(diào)成一臺(tái)穩(wěn)定扛住高并發(fā)推理的服務(wù)靠的是對(duì)顯存、調(diào)度和業(yè)務(wù)特征的綜合理解。個(gè)人項(xiàng)目建議從單卡加70億參數(shù)模型起步max-num-seqs從64開始?jí)簻y再逐步往上加。后續(xù)如果要擴(kuò)展可以把vLLM接入統(tǒng)一的模型網(wǎng)關(guān)做多模型路由、自動(dòng)擴(kuò)縮容那時(shí)候你會(huì)發(fā)現(xiàn)高并發(fā)推理這件事真正的大頭全在調(diào)度和資源管理上。