多卡分布式推理怎么做:從單卡到 8 節(jié)點(diǎn)集群的完整落地方案)
CLIP 多機(jī)多卡分布式推理怎么做從單卡到 8 節(jié)點(diǎn)集群的完整落地方案【免費(fèi)下載鏈接】CLIPCLIP (Contrastive Language-Image Pretraining), Predict the most relevant text snippet given an image項(xiàng)目地址: https://gitcode.com/GitHub_Trending/cl/CLIP如果你用 CLIP 做圖文匹配數(shù)據(jù)量一大單卡推理的耗時(shí)和顯存都會(huì)先頂不住。這篇文章面向新手和普通開發(fā)者把 CLIP 分布式推理講透先幫你判斷要不要上集群再講模型并行、數(shù)據(jù)并行、混合并行怎么選最后給出單機(jī)多卡到多機(jī)多卡的落地步驟、調(diào)優(yōu)手段和常見報(bào)錯(cuò)對(duì)策。讀完后你手上會(huì)有一套可以直接照著做的并行推理方案。先做判斷你的場(chǎng)景需要分布式嗎并行說白了就是把一份活兒拆給多塊 GPU 分頭干干完再匯總。但不是所有場(chǎng)景都該這么干——拆得不對(duì)通信開銷反而拖慢整體。先對(duì)照下面這張表做個(gè)選型你的情況建議方案原因單次推理 1 萬張圖片單卡 FP16 即可加集群的部署成本高于收益模型放不進(jìn)單卡顯存模型并行唯一出路必須拆模型模型放得下但數(shù)據(jù)量巨大數(shù)據(jù)并行每張卡存整份模型各算各的大模型 大數(shù)據(jù)如 ViT-L 級(jí) 百萬級(jí)樣本混合并行兩個(gè)瓶頸同時(shí)存在一句話清單幫你快速排除單張卡能裝下模型、batch 拉滿后還有余量且每天跑不滿幾小時(shí)→ 別折騰先把 FP16 和批處理調(diào)好顯存爆了CUDA out of memory但 CPU 內(nèi)存充足→ 優(yōu)先考慮模型并行吞吐不夠但顯存富余→ 數(shù)據(jù)并行通常性價(jià)比最高方案總覽三種并行策略怎么選CLIP 由視覺編碼器和文本編碼器兩部分組成在 clip/model.py 中VisionTransformer負(fù)責(zé)圖像側(cè)Transformertoken_embedding負(fù)責(zé)文本側(cè)。這個(gè)雙塔結(jié)構(gòu)天然適合拆分也決定了三種策略的適用邊界。模型并行Model Parallel把模型的不同層放到不同卡上前向時(shí)數(shù)據(jù)依次流過各卡。優(yōu)點(diǎn)是顯存占用線性下降缺點(diǎn)是每次前向都要跨卡傳激活值通信頻繁實(shí)現(xiàn)復(fù)雜。適合單卡塞不下的場(chǎng)景。數(shù)據(jù)并行Data Parallel每張卡存一份完整模型數(shù)據(jù)切片后各自前向推理結(jié)果直接拼接即可。推理場(chǎng)景下幾乎沒有通信成本不需要梯度同步是吞吐提升最直接的手段也是新手的首選?;旌喜⑿袃烧忒B加。例如文本編碼器小、留在每卡上視覺編碼器按層拆到 2 張卡。CLIP 的雙塔讓這種拆分比較自然視覺側(cè)按 Transformer 層數(shù)對(duì)半切文本側(cè)整塔復(fù)制。經(jīng)驗(yàn)法則先問模型放得下嗎放得下走數(shù)據(jù)并行放不下走模型并行或混合兩個(gè)瓶頸都有再上混合并行。上手準(zhǔn)備環(huán)境與依賴版本要求不高但 NCCL 和 CUDA 的版本組合要留意Python 3.8PyTorch 1.10torch.distributed接口更穩(wěn)CUDA 11.0NCCL 2.9依賴安裝git clone https://gitcode.com/GitHub_Trending/cl/CLIP cd CLIP pip install -r requirements.txt pip install -e .模型加載走項(xiàng)目自帶的load入口它會(huì)返回模型和預(yù)處理函數(shù)后面所有并行代碼都基于它展開。落地三步走從單機(jī)多卡到多機(jī)集群第一步單機(jī)多卡數(shù)據(jù)并行起步最穩(wěn)的起點(diǎn)。每個(gè)進(jìn)程加載一份模型各吃一個(gè)數(shù)據(jù)分片dist.init_process_group(backendnccl) rank int(os.environ[LOCAL_RANK]) torch.cuda.set_device(rank) model, preprocess clip.load(ViT-B/32, devicefcuda:{rank}) model.eval() # 每個(gè) rank 只處理自己分片的數(shù)據(jù) shard images[rank :: world_size] with torch.no_grad(): feats model.encode_image(preprocess(shard))啟動(dòng)命令python -m torch.distributed.launch --nproc_per_node4 infer.py推理場(chǎng)景下各卡結(jié)果互不依賴all_gather收集特征即可連DistributedDataParallel包裝都不需要——那更多是訓(xùn)練時(shí)的梯度同步工具。第二步大模型拆層做視覺塔模型并行當(dāng) ViT-L/14 這類大模型單卡裝不下時(shí)把視覺 Transformer 的殘差塊對(duì)半切開前一半放卡 0后一半放卡 1blocks model.visual.transformer.resblocks half len(blocks) // 2 class VisionSplit(nn.Module): def __init__(self, model): super().__init__() self.front nn.Sequential(*blocks[:half]) self.back nn.Sequential(*blocks[half:]) def forward(self, x): x self.front(x.to(cuda:0)) x self.back(x.to(cuda:1)) # 層間傳一次激活值 return x關(guān)鍵點(diǎn)就一處x.to(cuda:1)這一行就是層間通信切點(diǎn)選在殘差塊邊界能保持結(jié)構(gòu)完整避免切斷 LayerNorm。第三步擴(kuò)到多機(jī)用 rendezvous 替代手填參數(shù)多機(jī)部署時(shí)節(jié)點(diǎn)數(shù)、IP 都來自啟動(dòng)環(huán)境代碼里別再寫死# 每個(gè)節(jié)點(diǎn)執(zhí)行node_rank 逐機(jī)遞增 python -m torch.distributed.launch \ --nnodes2 --node_rank0 --nproc_per_node4 \ --master_addr節(jié)點(diǎn)0的IP --master_port29500 infer.py跨機(jī)網(wǎng)絡(luò)通常比機(jī)內(nèi) NVLink 慢一個(gè)數(shù)量級(jí)所以多機(jī)場(chǎng)景優(yōu)先保證數(shù)據(jù)并行為主、模型并行為輔機(jī)內(nèi)拆層、跨機(jī)只切數(shù)據(jù)能顯著壓低跨機(jī)通信量。調(diào)優(yōu)手冊(cè)讓推理更快更穩(wěn)通信推理能省則省。推理沒有反向傳播數(shù)據(jù)并行下每張卡只需在末尾all_gather一次特征中途任何為了對(duì)齊而同步的寫法都是浪費(fèi)。如果混入了訓(xùn)練邏輯比如帶loss.backward()非最后一步用model.no_sync()包起來減少梯度同步次數(shù)?;旌暇菷P16 先開。CLIP 的視覺塔對(duì) FP16 很友好顯存近乎減半model model.half() with torch.cuda.amp.autocast(): out model(image, text)個(gè)別數(shù)值敏感的層如logit_scale相關(guān)保持 FP32可避免偶發(fā) NaN。批大小按顯存余量動(dòng)態(tài)調(diào)。不是越大越好——批太大反而讓 kernel 選擇變差、顯存碎片增多。經(jīng)驗(yàn)起點(diǎn)ViT-B/32 約 64ViT-B/16 約 32ViT-L/14 約 16ViT-L/14336px 約 8再按實(shí)際 OOM 情況下調(diào)。調(diào)度數(shù)據(jù)按 rank 步長(zhǎng)取。data[rank::world_size]比按塊切更均衡能避免最后一卡空轉(zhuǎn)。踩坑記錄常見報(bào)錯(cuò)與對(duì)策現(xiàn)象大概率原因?qū)Σ逤UDA out of memory單卡負(fù)載過重拆模型并行或先上 FP16 降批大小任務(wù)卡在all_gather不動(dòng)跨機(jī)帶寬不足或某節(jié)點(diǎn)掉線用NCCL_P2P_DISABLE1排查 P2P 問題給任務(wù)加超時(shí)重派并行結(jié)果和單卡對(duì)不上切層位置不對(duì)切斷了 LN 或嵌入把切點(diǎn)移到殘差塊邊界對(duì)照 tests/test_consistency.py 的思路做一致性校驗(yàn)偶發(fā)輸出 NaN全 FP16 下數(shù)值溢出關(guān)鍵層投影、logit_scale鎖 FP32啟動(dòng)直接卡死不報(bào)錯(cuò)master 地址/端口沒打通先nc -vz master_addr master_port驗(yàn)證網(wǎng)絡(luò)另外提醒一句所有 rank 的模型加載必須用完全相同的參數(shù)和順序否則 NCCL 集合通信會(huì)在首次同步時(shí)直接 hang 住這類問題往往沒有明確報(bào)錯(cuò)。效果驗(yàn)證與收尾驗(yàn)證快沒快和對(duì)不對(duì)要分開做看吞吐固定數(shù)據(jù)集分別記錄單卡與并行后的樣本/秒。經(jīng)驗(yàn)上數(shù)據(jù)并行在推理場(chǎng)景接近線性加速8 卡數(shù)據(jù)并行拿到 6~7 倍是正常水平明顯低于這個(gè)數(shù)先查通信。看精度對(duì)同一批輸入比對(duì)并行輸出與單卡輸出的特征向量余弦相似度正常應(yīng) 0.999相似度掉了優(yōu)先懷疑切層位置或 FP16 溢出。項(xiàng)目?jī)?nèi)這些材料適合接著看基礎(chǔ)用法與零樣本預(yù)測(cè)notebooks/Interacting_with_CLIP.ipynb提示工程與分類器構(gòu)建notebooks/Prompt_Engineering_for_ImageNet.ipynb模型結(jié)構(gòu)與能力邊界model-card.md、README.md回到開頭那個(gè)問題先判斷要不要分布式再選策略最后才是堆機(jī)器。順序?qū)α硕鄼C(jī)多卡的 CLIP 推理就是一堆確定性的小步驟而不是玄學(xué)調(diào)參?!久赓M(fèi)下載鏈接】CLIPCLIP (Contrastive Language-Image Pretraining), Predict the most relevant text snippet given an image項(xiàng)目地址: https://gitcode.com/GitHub_Trending/cl/CLIP創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考