設(shè)施實(shí)戰(zhàn):GPU算力調(diào)度與推理服務(wù)優(yōu)化)
今天正式加入 Dynamia 密瓜智能以后很長(zhǎng)一段時(shí)間我都會(huì)泡在 AI 原生基礎(chǔ)設(shè)施這條線(xiàn)上。熟悉我的朋友都知道過(guò)去幾年我主要做分布式系統(tǒng)和云原生架構(gòu)接過(guò)不少訓(xùn)練平臺(tái)、推理服務(wù)的活但這次不是換個(gè)公司繼續(xù)干老本行而是要把“基礎(chǔ)設(shè)施”這個(gè)東西重新拆開(kāi)站在 AI 的視角再組裝一遍。這篇文章就當(dāng)我的開(kāi)工筆記把決定加入前后的思考、對(duì) AI 原生基礎(chǔ)設(shè)施的理解以及最近實(shí)操踩出來(lái)的經(jīng)驗(yàn)一并寫(xiě)清楚。如果你也在做模型訓(xùn)練、推理服務(wù)或者正在幫團(tuán)隊(duì)搭 GPU 算力平臺(tái)這篇文章應(yīng)該能給你一些參考。哪怕你現(xiàn)在只是剛接觸大模型只要搞明白“算力、存儲(chǔ)、網(wǎng)絡(luò)、調(diào)度、服務(wù)”這幾件事怎么協(xié)作后面看任何 AI Infra 相關(guān)的方案都會(huì)輕松很多。1. 為什么我從“跑模型”轉(zhuǎn)到“AI 原生基礎(chǔ)設(shè)施”先說(shuō)結(jié)論傳統(tǒng)云原生基礎(chǔ)設(shè)施解決的是“應(yīng)用怎么跑得穩(wěn)”AI 原生基礎(chǔ)設(shè)施解決的是“模型怎么跑得快、跑得省、跑得起”。這倆看起來(lái)都是基礎(chǔ)設(shè)施但底層邏輯完全不同。我過(guò)去搭過(guò)不少 Kubernetes 集群也幫團(tuán)隊(duì)做過(guò)微服務(wù)改造。那時(shí)候的核心關(guān)注點(diǎn)是容器的生命周期、配置管理、服務(wù)發(fā)現(xiàn)、彈性伸縮。一個(gè)典型場(chǎng)景是用戶(hù)請(qǐng)求量漲了HPA 自動(dòng)把 Pod 從 3 個(gè)擴(kuò)到 10 個(gè)流量降了再縮回來(lái)。這套體系放在 Web 服務(wù)上非常成熟OpenTelemetry、Prometheus、Ingress Controller 一套組合拳打下來(lái)基本能覆蓋 90% 的運(yùn)維需求。但放到 AI 場(chǎng)景里這套邏輯立刻露餡Web 請(qǐng)求是無(wú)狀態(tài)的模型推理請(qǐng)求是有狀態(tài)的。一個(gè)模型加載到顯存里可能要幾十秒甚至幾分鐘Pod 副本數(shù)隨便擴(kuò)容沒(méi)有任何問(wèn)題但模型副本不能隨便擴(kuò)顯存不夠就是不夠GPU 卡不插上去就不存在。Web 流量高峰可以排隊(duì)推理請(qǐng)求排隊(duì)需要額外管理。用戶(hù)可等不了一個(gè)整 Batch 慢慢湊延遲敏感業(yè)務(wù)對(duì) P99 的要求近乎苛刻。Web 資源可以按 CPU/內(nèi)存配額切分GPU 資源的切分顆粒度又貴又粗顯存、算力、帶寬彼此還會(huì)互相影響。換句話(huà)說(shuō)云原生基礎(chǔ)設(shè)施是“以容器為中心”AI 原生基礎(chǔ)設(shè)施是“以模型和 GPU 為中心”。倒不是說(shuō) K8s 在 AI 場(chǎng)景沒(méi)用而是光靠 K8s 那一套遠(yuǎn)遠(yuǎn)不夠你得在它上面重新設(shè)計(jì)一層面向模型、面向計(jì)算資源、面向數(shù)據(jù)流的邏輯。1.1 AI 原生基礎(chǔ)設(shè)施到底和“云原生 GPU”差在哪很多團(tuán)隊(duì)以為在 K8s 里加上 GPU 節(jié)點(diǎn)就能做 AI 平臺(tái)其實(shí)差距挺大的。我做了一張對(duì)照表能比較清楚地看到兩者的差異維度云原生基礎(chǔ)設(shè)施AI 原生基礎(chǔ)設(shè)施調(diào)度對(duì)象容器 / PodGPU 資源、顯存、模型副本彈性單位實(shí)例副本數(shù)批量推理任務(wù)、動(dòng)態(tài) Batch、顯存配額故障恢復(fù)重啟容器重新加載權(quán)重、檢查點(diǎn)恢復(fù)、斷點(diǎn)續(xù)訓(xùn)存儲(chǔ)需求低延遲熱數(shù)據(jù) 返回?cái)?shù)據(jù)超大模型文件、Checkpoint、數(shù)據(jù)集多渠道讀寫(xiě)網(wǎng)絡(luò)瓶頸微服務(wù)調(diào)用梯度同步、KV Cache 傳輸、分布式推理成本敏感點(diǎn)實(shí)例單價(jià) / 并發(fā)GPU 利用率、排隊(duì)等待、混合任務(wù)調(diào)度這也解釋了為什么現(xiàn)在大家開(kāi)始反復(fù)提“AI 原生”而不是簡(jiǎn)單說(shuō)“在 K8s 上跑 AI”。前者是從頭按 AI 工作負(fù)載的形狀來(lái)設(shè)計(jì)基礎(chǔ)設(shè)施后者只是把 AI 工作負(fù)載硬塞進(jìn)原有的基礎(chǔ)設(shè)施。1.2 這個(gè)賽道解決什么問(wèn)題加入 Dynamia 密瓜智能之前我和團(tuán)隊(duì)聊過(guò)幾次最終真正說(shuō)服我的不是 PPT是三個(gè)具體問(wèn)題第一算力利用率太難看。很多公司的 GPU 集群平均利用率不到 30%。訓(xùn)練任務(wù)白天跑推理服務(wù)晚上高峰中間還有大量碎片時(shí)間。把訓(xùn)練和推理放在同一個(gè)池子里動(dòng)態(tài)調(diào)度聽(tīng)上去簡(jiǎn)單做起來(lái)涉及 GPU 共享、顯存隔離、搶占策略每一步都是硬骨頭。第二大模型推理的延遲瓶頸。模型越來(lái)越大顯存放不下得做量化、蒸餾、分布式推理。推理框架選型、動(dòng)態(tài) Batch 調(diào)參、前置網(wǎng)關(guān)怎么做直接影響用戶(hù)體驗(yàn)和成本。第三數(shù)據(jù)流轉(zhuǎn)效率。訓(xùn)練前期要讀海量數(shù)據(jù)集訓(xùn)練過(guò)程中要高頻寫(xiě) Checkpoint訓(xùn)練完又要發(fā)布模型到推理集群。整個(gè)鏈條上如果存儲(chǔ)和緩存設(shè)計(jì)不合理GPU 再快也在等數(shù)據(jù)時(shí)干燒電。這三個(gè)問(wèn)題背后其實(shí)是同一個(gè)核心把 GPU 當(dāng)成一種需要精細(xì)調(diào)度的稀缺資源而不是可以隨便鋪的普通服務(wù)器。這也是 Dynamia 密瓜智能想做透的事。2. 一套 AI 原生基礎(chǔ)設(shè)施的“最小五件套”如果你也要從零搭一套 AI 原生基礎(chǔ)設(shè)施我的建議是先別急著上各種高級(jí)組件而是把下面五層搞清楚。這五層是一個(gè)可運(yùn)行的最小骨架之后所有平臺(tái)能力都是在這五層之上逐步長(zhǎng)出來(lái)的。2.1 算力層GPU 節(jié)點(diǎn)選型與配置算力層很容易被理解成“買(mǎi)卡就行”實(shí)際遠(yuǎn)不止。GPU 節(jié)點(diǎn)配置要同時(shí)考慮三件事GPU 型號(hào)、CPU/內(nèi)存配比、互聯(lián)拓?fù)?。GPU 型號(hào)直接決定了你能跑多大的模型。以常見(jiàn)的單卡顯存為例一張卡 80GB 和一張卡 24GB 能承載的模型規(guī)模差非常多。顯存不夠就得做模型并行或者切分這會(huì)引入額外的通信開(kāi)銷(xiāo)所以很多時(shí)候?qū)幙蛇x大顯存卡。CPU/內(nèi)存配比容易被忽略。數(shù)據(jù)預(yù)處理、Tokenize、動(dòng)態(tài) Batch、Python 運(yùn)行時(shí)這些都會(huì)吃 CPU 和內(nèi)存如果節(jié)點(diǎn)里 CPU 核數(shù)太少GPU 會(huì)經(jīng)??盏葦?shù)據(jù)。我見(jiàn)過(guò)一個(gè)實(shí)例數(shù)據(jù)管道沒(méi)做好GPU 利用率只有 40%CPU 卻 100% 跑滿(mǎn)典型的一核有難、八核圍觀?;ヂ?lián)拓?fù)涓P(guān)鍵。多卡訓(xùn)練時(shí)卡與卡之間的通信帶寬直接決定了訓(xùn)練效率。NVLink 和普通 PCIe 的帶寬差距可能是數(shù)量級(jí)的。選機(jī)器的時(shí)候我建議問(wèn)清楚卡間互聯(lián)方式別光看卡數(shù)。至少要讓同一臺(tái)機(jī)器上的跨卡通信走高速互聯(lián)跨機(jī)通信再另外規(guī)劃 RDMA 或高性能網(wǎng)絡(luò)。2.2 存儲(chǔ)層模型倉(cāng)庫(kù)、數(shù)據(jù)集與檢查點(diǎn)AI 場(chǎng)景的存儲(chǔ)需求和普通業(yè)務(wù)完全不同。一個(gè)模型權(quán)重文件動(dòng)輒幾十 GBCheckpoint 可能要寫(xiě)幾百 GB數(shù)據(jù)集又是大量小文件加少量超大文件混合。這時(shí)候很難用單一存儲(chǔ)方案通吃。我的建議是分層處理訓(xùn)練數(shù)據(jù)用并行文件系統(tǒng)或者高性能對(duì)象存儲(chǔ)核心指標(biāo)是高吞吐和大并發(fā)能扛住成百上千個(gè)數(shù)據(jù)加載進(jìn)程同時(shí)讀。模型文件用對(duì)象存儲(chǔ) 本地緩存。推理節(jié)點(diǎn)啟動(dòng)時(shí)先從對(duì)象存儲(chǔ)拉權(quán)重但每次都拉一遍顯然不現(xiàn)實(shí)所以節(jié)點(diǎn)上要有本地緩存層最好再配合模型預(yù)熱機(jī)制。Checkpoint 寫(xiě)入用高帶寬并行存儲(chǔ)并且要有版本管理。訓(xùn)練崩了要能快速回滾到最近一次健康狀態(tài)而不是從頭再來(lái)。存儲(chǔ)層最怕的是“看起來(lái)能存實(shí)際一壓就垮”。很多團(tuán)隊(duì)一開(kāi)始圖省事用了常規(guī)文件存儲(chǔ)結(jié)果并行訓(xùn)練一開(kāi)存儲(chǔ)帶寬直接被打滿(mǎn)訓(xùn)練速度反而被存儲(chǔ)拖慢。這一塊不能省。2.3 網(wǎng)絡(luò)層分布式訓(xùn)練與推理的隱形命脈模型規(guī)模一大單卡、單機(jī)都裝不下分布式是必然選擇。分布式訓(xùn)練里最核心的通信模式是 AllReduce每一輪梯度同步都需要所有節(jié)點(diǎn)互相傳數(shù)據(jù)這種通信對(duì)帶寬和延遲極其敏感。普通以太網(wǎng)下幾百?gòu)埧ㄒ黄鹜介_(kāi)銷(xiāo)會(huì)迅速吃掉訓(xùn)練收益。所以 AI 原生基礎(chǔ)設(shè)施的網(wǎng)絡(luò)設(shè)計(jì)重點(diǎn)不是對(duì)外提供多少帶寬而是內(nèi)部東西向流量的延遲和吞吐。RDMA 技術(shù)已經(jīng)是分布式訓(xùn)練場(chǎng)景的事實(shí)標(biāo)準(zhǔn)。當(dāng)然不是說(shuō)沒(méi)有 RDMA 就跑不了分布式訓(xùn)練而是規(guī)模上來(lái)之后這是繞不開(kāi)的性能分水嶺。推理側(cè)的網(wǎng)絡(luò)壓力也開(kāi)始變大。現(xiàn)在很多團(tuán)隊(duì)做 Prefill 和 Decode 分離把 Prefill 階段的中間結(jié)果通過(guò)高速網(wǎng)絡(luò)傳給 Decode 節(jié)點(diǎn)跨機(jī)傳輸?shù)臄?shù)據(jù)量比傳統(tǒng)請(qǐng)求大很多網(wǎng)絡(luò)設(shè)計(jì)必須提前考慮。2.4 調(diào)度與編排層誰(shuí)來(lái)決定這塊 GPU 給誰(shuí)用我在加入前最看重的就是這一層。沒(méi)有調(diào)度所有 GPU 資源就是一堆散落的算力談不上平臺(tái)。調(diào)度層首先要感知 GPU 資源。節(jié)點(diǎn)上有幾張卡、多少顯存空閑、是否已經(jīng)跑著任務(wù)都要能實(shí)時(shí)掌握。不能只看節(jié)點(diǎn)剩余 CPU 和內(nèi)存因?yàn)閮蓚€(gè)節(jié)點(diǎn)即使 CPU 相同GPU 型號(hào)不同能跑的任務(wù)也完全不同。其次要支持多級(jí)調(diào)度策略。訓(xùn)練任務(wù)通常跑得久、資源需求大推理任務(wù)需要快速響應(yīng)、延遲敏感。這兩種任務(wù)混在同一個(gè)集群里需要一個(gè)能區(qū)分優(yōu)先級(jí)、能搶占、能排隊(duì)的調(diào)度器。比如高峰期的交互式推理請(qǐng)求應(yīng)該優(yōu)先離線(xiàn)批量訓(xùn)練可以排后。最后還要處理 GPU 共享和顯存隔離。一張卡上跑多個(gè)推理任務(wù)可以大幅提升利用率但顯存配額的硬隔離必須到位否則一個(gè)任務(wù)超顯存會(huì)把同卡上的其他任務(wù)一起打掛。2.5 接入層模型服務(wù)與推理網(wǎng)關(guān)模型訓(xùn)練得再好最終要通過(guò)服務(wù)暴露出去才有價(jià)值。接入層是用戶(hù)第一眼看到的東西也是延遲和成本控制的關(guān)鍵戰(zhàn)場(chǎng)。我比較推薦的模式是“模型服務(wù)引擎 推理網(wǎng)關(guān)”兩層。模型服務(wù)引擎負(fù)責(zé)真正加載模型、執(zhí)行推理常見(jiàn)的有 vLLM、Triton 這類(lèi)框架它們內(nèi)部已經(jīng)做了 PagedAttention、動(dòng)態(tài) Batch 等優(yōu)化。推理網(wǎng)關(guān)則負(fù)責(zé)請(qǐng)求路由、鑒權(quán)、限流、排隊(duì)、超時(shí)管理相當(dāng)于模型世界的 API Gateway。兩層分離的好處是引擎可以專(zhuān)注性能優(yōu)化網(wǎng)關(guān)可以專(zhuān)注接入邏輯。以后模型版本迭代比如從 7B 換到 13B只需要在網(wǎng)關(guān)層調(diào)整路由規(guī)則不需要改動(dòng)整體接入鏈路。另外推理網(wǎng)關(guān)還承擔(dān)流控職責(zé)防止突發(fā)流量把模型服務(wù)打爆。3. 落地過(guò)程中的關(guān)鍵設(shè)計(jì)我偏向的四個(gè)選擇有了最小五件套的骨架接下來(lái)就是更細(xì)的設(shè)計(jì)選擇。這些選擇沒(méi)有絕對(duì)的對(duì)錯(cuò)更多是結(jié)合業(yè)務(wù)形態(tài)做取舍。我這里把自己認(rèn)為值得參考的四個(gè)決策點(diǎn)寫(xiě)出來(lái)。3.1 訓(xùn)練和推理共用集群而不是物理隔離很多團(tuán)隊(duì)習(xí)慣把訓(xùn)練集群和推理集群分開(kāi)管理簡(jiǎn)單但資源利用率很低。白天推理業(yè)務(wù)少的時(shí)候GPU 閑置著晚上訓(xùn)練任務(wù)跑完算力又空著。分開(kāi)部署兩邊都在浪費(fèi)。我偏好的做法是訓(xùn)練推理共用同一個(gè)資源池但用調(diào)度策略區(qū)分優(yōu)先級(jí)。交互式推理請(qǐng)求優(yōu)先級(jí)最高可以搶占低優(yōu)先級(jí)離線(xiàn)訓(xùn)練任務(wù)離線(xiàn)訓(xùn)練任務(wù)則把資源利用的空窗填滿(mǎn)。這個(gè)設(shè)計(jì)對(duì)調(diào)度器的要求高但收益也很直接同樣的 GPU 總量月產(chǎn)出至少多出兩成。3.2 GPU 共享用顯存硬隔離不用裸跑裸占一張 80GB 的卡如果只跑一個(gè)大模型內(nèi)存利用率太難看。我很看好 GPU 共享的方向但實(shí)現(xiàn)方式必須講究。硬件層面的 MIG 或者虛擬化方案能做到比較強(qiáng)的隔離一張卡切幾個(gè)實(shí)例互不干擾。軟件層面的時(shí)間切片能提升利用率但隔離性弱一個(gè)任務(wù)的異常容易殃及同卡鄰居。我的習(xí)慣是在生產(chǎn)環(huán)境用硬件級(jí)隔離或容器級(jí)顯存限制寧可單卡利用率低一點(diǎn)也要保證故障隔離和安全邊界。測(cè)試環(huán)境可以放開(kāi)時(shí)間切片怎么壓都行。3.3 推理請(qǐng)求先排隊(duì)再動(dòng)態(tài) Batch動(dòng)態(tài) Batch 能大幅提升推理吞吐。原理很簡(jiǎn)單把短時(shí)間內(nèi)的多個(gè)請(qǐng)求攢在一起湊成一個(gè) Batch 喂給模型利用 GPU 的并行計(jì)算能力同時(shí)處理多個(gè)請(qǐng)求代價(jià)是第一個(gè)請(qǐng)求會(huì)稍微多等一會(huì)。這里的關(guān)鍵參數(shù)是 Batch 窗口。窗口太短攢不住請(qǐng)求Batch 效果不明顯窗口太長(zhǎng)延遲飆升用戶(hù)體驗(yàn)崩掉。我一般會(huì)從 20ms 起步調(diào)觀察 P99 延遲和吞吐曲線(xiàn)找到剪刀差最小的點(diǎn)。另一個(gè)調(diào)整方向是優(yōu)先聚合同類(lèi)請(qǐng)求讓同一個(gè) Batch 內(nèi)部模型保持一致避免不同模型來(lái)回切換導(dǎo)致緩存失效。3.4 模型發(fā)布要可回滾版本要可追溯模型上線(xiàn)之后不是萬(wàn)事大吉。線(xiàn)上效果變差、數(shù)據(jù)分布漂移、推理結(jié)果異常都需要快速回滾到之前的版本。所以模型倉(cāng)庫(kù)里的每個(gè)模型都要有版本號(hào)、訓(xùn)練日志、評(píng)估指標(biāo)發(fā)布時(shí)要走灰度流程。灰度推理是我比較強(qiáng)調(diào)的環(huán)節(jié)。先切 5% 流量到新模型觀察反饋確認(rèn)沒(méi)問(wèn)題再逐步放量。一旦異常指標(biāo)出現(xiàn)網(wǎng)關(guān)層要能立刻切回舊版本。這個(gè)流程依賴(lài)模型網(wǎng)關(guān)的路由能力所以 2.5 里我特意強(qiáng)調(diào)網(wǎng)關(guān)的重要性。4. 從零跑通一個(gè) AI 推理服務(wù)的實(shí)操記錄理論說(shuō)了不少上點(diǎn)實(shí)操。最近我在 Dynamia 密瓜智能的測(cè)試環(huán)境里搭了一套最小推理服務(wù)從裸機(jī)到能調(diào)通接口大致花了一個(gè)下午。把過(guò)程寫(xiě)下來(lái)給你一個(gè)可以照著做的模板。4.1 環(huán)境準(zhǔn)備驅(qū)動(dòng)、容器運(yùn)行時(shí)、GPU 識(shí)別正常步驟是先裝 GPU 驅(qū)動(dòng)再裝容器運(yùn)行時(shí)最后讓 K8s 識(shí)別到 GPU 資源。如果只是單機(jī)驗(yàn)證可以用 Docker 直接跑但生產(chǎn)環(huán)境建議還是走 K8s。這里重點(diǎn)檢查一件事容器里能不能看到 GPU。很多坑都出在驅(qū)動(dòng)版本和容器運(yùn)行時(shí)版本不匹配上。驗(yàn)證命令很簡(jiǎn)單跑一個(gè)帶 GPU 的測(cè)試容器執(zhí)行nvidia-smi能看到卡信息基本就通了。注意驅(qū)動(dòng)裝完別忘了重啟節(jié)點(diǎn)。很多人漏了這一步結(jié)果nvidia-smi在宿主機(jī)上正常容器里怎么都看不到卡。4.2 部署模型服務(wù)引擎我這次用的是 vLLM 來(lái)加載模型。先拉一個(gè)精簡(jiǎn)模型做起驗(yàn)證配置核心參數(shù)時(shí)給兩點(diǎn)建議max-model-len不要設(shè)置太大。很多人喜歡把上下文窗口開(kāi)滿(mǎn)實(shí)測(cè)下來(lái)顯存占用會(huì)明顯上升如果業(yè)務(wù)很少用到超長(zhǎng)輸入設(shè)一個(gè)合理的值更經(jīng)濟(jì)。gpu-memory-utilization一般設(shè) 0.85 到 0.9。別設(shè)到 0.95 以上顯存接近滿(mǎn)載時(shí)碎片化問(wèn)題會(huì)直接影響并發(fā)能力和穩(wěn)定性。模型服務(wù)引擎的啟動(dòng)命令大概長(zhǎng)這樣python -m vllm.entrypoints.openai.api_server \ --model /data/models/qwen2-7b-instruct \ --served-model-name qwen2-7b \ --max-model-len 8192 \ --gpu-memory-utilization 0.9 \ --port 8000啟動(dòng)成功后可以用一個(gè)最簡(jiǎn)單的請(qǐng)求驗(yàn)證curl http://127.0.0.1:8000/v1/chat/completions \ -H Content-Type: application/json \ -d { model: qwen2-7b, messages: [{role: user, content: 你好}] }能正常返回說(shuō)明模型服務(wù)引擎已經(jīng)通了。4.3 加一層網(wǎng)關(guān)做路由和限流單機(jī)驗(yàn)證沒(méi)問(wèn)題接生產(chǎn)還需要在前面加網(wǎng)關(guān)。網(wǎng)關(guān)要處理的事情包括請(qǐng)求路由到正確的模型服務(wù)、接口鑒權(quán)、Token 限流、排隊(duì)超時(shí)等。這層我用的是比較通用的方案Kong 或者 APISIX 都可以。關(guān)鍵是配置路由規(guī)則把/v1/chat/completions的請(qǐng)求轉(zhuǎn)發(fā)到 vLLM 的 8000 端口并給每個(gè)調(diào)用方配好 QPS 上限。網(wǎng)關(guān)層我額外加了兩個(gè)參數(shù)連接超時(shí)和讀超時(shí)。模型推理比較慢超時(shí)設(shè)太短會(huì)誤殺正常請(qǐng)求設(shè)太長(zhǎng)又會(huì)讓異常請(qǐng)求長(zhǎng)期占據(jù)連接。我會(huì)把默認(rèn)讀超時(shí)設(shè)成 120 秒因?yàn)殚L(zhǎng)文本生成的耗時(shí)確實(shí)可能到分鐘級(jí)。最大排隊(duì)數(shù)。超出排隊(duì)上限直接返回 429 錯(cuò)誤避免雪崩效應(yīng)。這樣做之后調(diào)用方拿到的是一套穩(wěn)定的 API后端模型是哪個(gè)、要不要擴(kuò)容調(diào)用方完全不用關(guān)心。4.4 壓測(cè)與指標(biāo)觀察服務(wù)起來(lái)之后一定要壓測(cè)別直接上生產(chǎn)。我用的壓測(cè)工具是簡(jiǎn)單的 locust 腳本構(gòu)造一批并發(fā)請(qǐng)求同時(shí)盯四個(gè)指標(biāo)QPS、TTFT首 Token 延遲、Token 生成速率、GPU 利用率。第一輪壓測(cè)我通常會(huì)把并發(fā)從 1 逐步加到 50觀察延遲曲線(xiàn)。如果 QPS 不再線(xiàn)性增長(zhǎng)說(shuō)明系統(tǒng)進(jìn)入瓶頸區(qū)再壓下去只會(huì)讓延遲劇增。這個(gè)瓶頸點(diǎn)的數(shù)據(jù)就是后續(xù)做容量評(píng)估和成本預(yù)估的依據(jù)。壓測(cè)結(jié)果出來(lái)后我會(huì)回到 3.3 提到的動(dòng)態(tài) Batch 參數(shù)重新調(diào) Batch 窗口和并發(fā)限制。實(shí)測(cè)下來(lái)調(diào)優(yōu)后 QPS 翻倍是很常見(jiàn)的事。5. 最近踩過(guò)的三個(gè)真實(shí)坑再來(lái)點(diǎn)更接地氣的。下面的問(wèn)題都是我在實(shí)操中真實(shí)遇到過(guò)的網(wǎng)上資料不太會(huì)這么集中地寫(xiě)我整理出來(lái)給同行參考。5.1 GPU 顯存泄漏服務(wù)越跑越慢現(xiàn)象模型服務(wù)剛啟動(dòng)時(shí)延遲很好跑兩三天后延遲逐漸變高最后 OOM 崩潰。排查過(guò)程先看進(jìn)程內(nèi)存和顯存占用發(fā)現(xiàn)顯存使用率持續(xù)走高。再用 Nvidia 的調(diào)試工具抓 CUDA 緩存狀態(tài)確認(rèn)是部分請(qǐng)求結(jié)束后沒(méi)有正確釋放顯存。常見(jiàn)誘因是自定義模型邏輯里創(chuàng)建了 CUDA 張量但沒(méi)有顯式清理或者某些庫(kù)版本存在內(nèi)存碎片問(wèn)題。結(jié)論顯存泄漏問(wèn)題很難完全避免但可以通過(guò)定期滾動(dòng)重啟來(lái)止血更治本的做法是升級(jí)推理框架版本并確保模型代碼里的臨時(shí)張量都走with torch.cuda.device這類(lèi)規(guī)范寫(xiě)法。注意上線(xiàn)前壓測(cè)不要只壓 10 分鐘至少要壓幾個(gè)小時(shí)甚至幾天才能暴露出泄漏問(wèn)題。很多人就是栽在短壓測(cè)看起來(lái)一切正常。5.2 高峰時(shí)段請(qǐng)求排隊(duì)過(guò)深P99 延遲爆炸現(xiàn)象業(yè)務(wù)高峰期 P99 延遲從 300ms 飆到 5 秒甚至出現(xiàn)調(diào)用超時(shí)。排查過(guò)程檢查網(wǎng)關(guān)日志發(fā)現(xiàn)高峰期排隊(duì)數(shù)非常大模型服務(wù)的 Batch 窗口又過(guò)長(zhǎng)導(dǎo)致大量請(qǐng)求堆在等待隊(duì)列里。再往下查真實(shí)原因是模型副本數(shù)不夠GPU 資源上限到了加排隊(duì)只是把問(wèn)題從“超時(shí)”變成長(zhǎng)尾。結(jié)論合理的做法是高峰期自動(dòng)擴(kuò)容模型副本并設(shè)置最大排隊(duì)深度拒絕掉一些可接受的流量。不能只顧著保護(hù)后端無(wú)限制地堆積請(qǐng)求這樣會(huì)把所有用戶(hù)的體驗(yàn)都拖差。5.3 多租戶(hù)任務(wù)互相干擾一個(gè)任務(wù)寫(xiě)爆共享目錄現(xiàn)象同一個(gè)訓(xùn)練集群里兩個(gè)團(tuán)隊(duì)跑任務(wù)其中一個(gè)瘋狂寫(xiě)臨時(shí)文件把共享存儲(chǔ)打滿(mǎn)導(dǎo)致另一個(gè)團(tuán)隊(duì)的 Checkpoint 寫(xiě)不進(jìn)去。排查過(guò)程查存儲(chǔ)看是單個(gè)大文件占空間還是一堆小文件占 inode。這次更隱蔽單個(gè)文件不大但數(shù)量幾百萬(wàn)個(gè)把共享目錄的 inode 打滿(mǎn)了。結(jié)論租戶(hù)隔離不只是算力隔離存儲(chǔ)配額和文件數(shù)限制也要做。我后來(lái)給每個(gè)租戶(hù)單獨(dú)目錄設(shè)置容量配額和文件數(shù)配額并對(duì)臨時(shí)文件做自動(dòng)清理策略問(wèn)題才徹底解決。癥狀可能原因解決辦法顯存持續(xù)上漲最終 OOM推理框架顯存泄漏未釋放緩存升級(jí)框架版本規(guī)范臨時(shí)張量清理定期滾動(dòng)重啟P99 延遲飆升隊(duì)列堆積過(guò)深模型副本不足擴(kuò)容副本設(shè)置最大排隊(duì)數(shù)和超時(shí)策略共享目錄空間或 inode 打滿(mǎn)租戶(hù)任務(wù)寫(xiě)臨時(shí)文件無(wú)節(jié)制配置容量配額、文件數(shù)配額、自動(dòng)清理請(qǐng)求偶發(fā)返回 500 或超時(shí)模型加載中壓測(cè)后冷啟動(dòng)問(wèn)題增加模型預(yù)熱機(jī)制用就緒探針控制流量多卡訓(xùn)練速度上不去卡間通信走普通 PCIe帶寬不足改高速互聯(lián)優(yōu)化數(shù)據(jù)并行和梯度同步策略6. 我對(duì)接下來(lái)的方向判斷加入 Dynamia 密瓜智能之后我把未來(lái)一段時(shí)間的工作重點(diǎn)分成三個(gè)階段。第一個(gè)階段是把現(xiàn)有集群的利用率打上去通過(guò)細(xì)粒度的調(diào)度和副本管理先把空閑 GPU 盤(pán)活。第二個(gè)階段是把推理服務(wù)標(biāo)準(zhǔn)化給業(yè)務(wù)方提供一致的接入體驗(yàn)內(nèi)部模型怎么部署、怎么灰度、怎么回滾都做成標(biāo)準(zhǔn)流程。第三個(gè)階段是更長(zhǎng)期的事情做訓(xùn)練推理一體化的資源編排讓一個(gè)資源池能同時(shí)支撐訓(xùn)練和推理的復(fù)雜混合負(fù)載。這三個(gè)階段里我對(duì)第三個(gè)階段最感興趣。很多人覺(jué)得訓(xùn)練和推理是兩個(gè)系統(tǒng)訓(xùn)練平臺(tái)管分布式任務(wù)推理平臺(tái)管在線(xiàn)服務(wù)。但它們的底層資源明明是同一批 GPU。如果能把檢查點(diǎn)恢復(fù)、模型預(yù)熱、動(dòng)態(tài)擴(kuò)容這些能力整合到一個(gè)系統(tǒng)里AI 團(tuán)隊(duì)從開(kāi)發(fā)到上線(xiàn)再到迭代的效率會(huì)提升一個(gè)大的臺(tái)階。老實(shí)說(shuō)這個(gè)方向沒(méi)人敢說(shuō)完全做透了??ㄅc卡之間的調(diào)度、顯存與算力的隔離、存儲(chǔ)與網(wǎng)絡(luò)的配合每一個(gè)環(huán)節(jié)都有大量?jī)?yōu)化空間。正因?yàn)槿绱诉@件事才值得認(rèn)真做。這幾個(gè)月我自己最大的體會(huì)是AI 原生基礎(chǔ)設(shè)施不是買(mǎi)一堆卡然后寫(xiě)個(gè) Kubernetes 部署文件那么簡(jiǎn)單它更像把算力當(dāng)成一門(mén)生意來(lái)精細(xì)化運(yùn)營(yíng)。每一塊 GPU 的利用率、每一次推理的延遲、每一個(gè)任務(wù)的排隊(duì)時(shí)間最后都會(huì)變成實(shí)實(shí)在在的成本和用戶(hù)體驗(yàn)。這個(gè)項(xiàng)目后續(xù)我能延展的東西還很多后面有新的進(jìn)展或者踩到新坑再回來(lái)寫(xiě)文章繼續(xù)跟大家聊。