:從PCIe瓶頸到全交換架構(gòu)實(shí)戰(zhàn))
簡(jiǎn)介這份資料面向具備一定硬件基礎(chǔ)、關(guān)注AI芯片與GPU架構(gòu)的工程師和技術(shù)人員系統(tǒng)梳理GPU工作原理與多GPU互聯(lián)通信體系。內(nèi)容從GPU邏輯模塊劃分、圖形處理流程與軟件棧切入深入解析英偉達(dá)從Fermi到Hopper的架構(gòu)演進(jìn)并重點(diǎn)展開NVLink各代帶寬與連接數(shù)變化以及NVSwitch節(jié)點(diǎn)交換架構(gòu)的內(nèi)部結(jié)構(gòu)、電路設(shè)計(jì)、帶寬性能與最新功能幫助讀者理解如何借助NVSwitch優(yōu)化多GPU集群的通信效率。資源包共1個(gè)PDF文件約17.3MB內(nèi)容基于華為昇騰平臺(tái)資料整理技術(shù)細(xì)節(jié)與參數(shù)兼具專業(yè)性和前沿性并附有豐富參考資料鏈接便于進(jìn)一步查閱文獻(xiàn)。目前已有286人學(xué)習(xí)適合希望深入掌握GPU互聯(lián)與NVSwitch架構(gòu)的讀者研讀。1. 從 PCIe 瓶頸到 NVSwitch多 GPU 互聯(lián)到底在解決什么問題單卡跑得歡一上多卡就拉胯——這是很多做并行計(jì)算的人都會(huì)撞上的墻。你手里有 8 張卡模型切分之后每張卡只算一部分但每算完一層就得跟其他卡同步梯度、交換激活值。如果這些通信全走 PCIe帶寬就那么點(diǎn)GPU 算得再快也得停下來(lái)等數(shù)據(jù)利用率直接腰斬。GPU 架構(gòu)本身是為大規(guī)模并行設(shè)計(jì)的SM 核心、HBM2 顯存、XBAR 交換結(jié)構(gòu)一應(yīng)俱全但卡與卡之間的通路如果還是傳統(tǒng)總線整個(gè)系統(tǒng)的天花板就被鎖死了。NVLink 和 NVSwitch 就是沖著這個(gè)瓶頸來(lái)的。NVLink 把 GPU 之間的直連帶寬從 PCIe 的幾十 GB/s 拉到幾百 GB/sNVSwitch 則進(jìn)一步把多卡互聯(lián)從“兩兩握手”變成“全交換架構(gòu)”讓 8 卡甚至 16 卡之間可以同時(shí)高速通信。這套東西直接決定了分布式訓(xùn)練、高性能計(jì)算集群能不能把多卡用出線性加速比。如果你正在搭多卡訓(xùn)練環(huán)境、調(diào) NCCL 通信參數(shù)或者單純想搞明白 DGX 服務(wù)器內(nèi)部到底怎么連的這份資料值得細(xì)看。2. GPU 內(nèi)部架構(gòu)與 NVLink 通信原理從 SM 到 XBAR 的數(shù)據(jù)通路2.1 GPU 邏輯模塊劃分與 AI 編程本質(zhì)一塊 GPU 不是一個(gè) monolithic 的大核心而是由多個(gè) GPCGraphics Processing Cluster組成每個(gè) GPC 下面掛若干 SMStreaming Multiprocessor。SM 是真正干活的最小單元里面有 CUDA Core、Tensor Core、寄存器堆、共享內(nèi)存和調(diào)度器。當(dāng)你寫 CUDA kernel 時(shí)線程塊被分配到各個(gè) SM 上SM 再把線程分成 warp 去執(zhí)行。HBM2 顯存掛在 GPU 邊緣所有 SM 通過片上互聯(lián)網(wǎng)絡(luò)訪問顯存。這里有個(gè)關(guān)鍵點(diǎn)SM 之間的數(shù)據(jù)共享是通過 HBM2 中轉(zhuǎn)的不是直接 SM-to-SM 通信。也就是說(shuō)SM A 算完的結(jié)果要寫回 HBM2SM B 再?gòu)?HBM2 讀。這個(gè)設(shè)計(jì)簡(jiǎn)化了硬件但也意味著顯存帶寬是共享資源。AI 編程的本質(zhì)就是讓盡可能多的 SM 同時(shí)忙起來(lái)同時(shí)讓數(shù)據(jù)在 HBM2 和 SM 之間的流動(dòng)盡可能高效。常見做法是用 shared memory 做塊內(nèi)數(shù)據(jù)復(fù)用用寄存器做線程級(jí)緩存減少對(duì) HBM2 的重復(fù)訪問。2.2 從 PCIe 到 NVLinkGPU 間通信的帶寬演進(jìn)早期多 GPU 系統(tǒng)里GPU 之間通信必須經(jīng)過 PCIe 總線而且往往要 CPU 參與調(diào)度。GPU A 要把數(shù)據(jù)發(fā)給 GPU B路徑是 GPU A → PCIe → CPU → PCIe → GPU B。這個(gè)過程中 CPU 成了中間人PCIe 帶寬成了硬瓶頸。PCIe 3.0 x16 的理論帶寬是 16 GB/s 左右實(shí)際有效帶寬更低對(duì)于動(dòng)輒幾百 MB 的梯度同步來(lái)說(shuō)延遲和帶寬都不夠看。NVLink 的思路很直接在 GPU 之間拉一條專用高速鏈路不經(jīng)過 CPU 和 PCIe。第一代 NVLink 每 GPU 提供 160 GB/s 帶寬到第四代已經(jīng)到 900 GB/s。更關(guān)鍵的是NVLink 讓 GPU 可以直接訪問其他 GPU 的 HBM2 顯存通過 LD/ST 指令或者 RDMA 操作不需要把數(shù)據(jù)先拷貝到本地。XBAR 作為橋接器把多個(gè) NVLink 端口連接起來(lái)形成一個(gè)交換網(wǎng)絡(luò)。這樣 GPU 之間的通信就不再是“繞路走”而是“直連高速通道”。2.3 NVSwitch 的出現(xiàn)從兩兩互聯(lián)到全交換架構(gòu)NVLink 解決了點(diǎn)對(duì)點(diǎn)帶寬問題但拓?fù)浣Y(jié)構(gòu)有局限。第一代 NVLink 每 GPU 只有 4 個(gè)鏈路8 卡全互聯(lián)需要每張卡都跟其他 7 張卡直連鏈路數(shù)不夠。實(shí)際部署中只能做部分連接比如環(huán)形或網(wǎng)狀通信效率取決于任務(wù)模式。如果某個(gè) all-reduce 操作需要所有卡同時(shí)交換數(shù)據(jù)部分連接的拓?fù)渚蜁?huì)產(chǎn)生擁塞。NVSwitch 的本質(zhì)是一塊獨(dú)立的 NVLink 交換芯片提供 18 路 NVLink 接口。每塊 V100 的 6 路 NVLink 分別連接到 6 塊 NVSwitch 上8 塊 GPU 和 6 塊 NVSwitch 構(gòu)成一個(gè)基板實(shí)現(xiàn)完全無(wú)阻塞的全互聯(lián)。任意兩塊 GPU 之間通信都是兩跳GPU → NVSwitch → GPU而且所有 GPU 對(duì)可以同時(shí)以 300 GB/s 的速度通信??偩酆蠋掃_(dá)到 2.4 TB/s。這個(gè)架構(gòu)讓多卡系統(tǒng)從“盡力而為的互聯(lián)”變成“交換式全互聯(lián)”通信模式不再受拓?fù)湎拗啤?. NVSwitch 硬件細(xì)節(jié)與部署配置參數(shù)、帶寬與連接方式3.1 NVSwitch 芯片規(guī)格與電路設(shè)計(jì)第一代 NVSwitch 基于臺(tái)積電 12nm FinFET 工藝晶體管數(shù)量 20 億Die Size 106 mm2功耗 100W。封裝在 1940 個(gè) pin 的 BGA 芯片中面積約 4 cm2。其中 576 個(gè)針腳專門服務(wù)于 18 路 NVLink剩下的用于電源和管理接口包括 x4 PCIe、I2C、GPIO 等。電路設(shè)計(jì)上有幾個(gè)值得注意的點(diǎn)。XBAR 交換邏輯非常緊湊數(shù)據(jù)包的處理和交換在片上完成。I/O 塊占據(jù)了超過 50% 的芯片面積這是有意為之——最大化物理鏈接電路的面積比保證信號(hào)完整性。所有 NVLink 端口在電路上并行排列簡(jiǎn)化了封裝襯底的布線。NVSwitch 復(fù)用了 V100 的 NVLink IP 塊和 XBAR 設(shè)計(jì)驗(yàn)證能力降低了開發(fā)風(fēng)險(xiǎn)。參數(shù)第一代 NVSwitch第二代第三代每 GPU 雙向帶寬300 GB/s600 GB/s900 GB/s總聚合帶寬2.4 TB/s4.8 TB/s7.2 TB/s支持 GPU 數(shù)888對(duì)應(yīng)架構(gòu)VoltaAmpereHopper3.2 多 GPU 系統(tǒng)連接配置與驗(yàn)證步驟搭建或驗(yàn)證 NVLink/NVSwitch 系統(tǒng)時(shí)第一步是確認(rèn)拓?fù)?。?Linux 環(huán)境下用nvidia-smi topo -m可以看到 GPU 之間的連接矩陣。如果顯示NV#表示走 NVLinkPIX或PHB表示走 PCIe。對(duì)于 NVSwitch 系統(tǒng)所有 GPU 對(duì)之間應(yīng)該顯示NV#而且是對(duì)稱的。# 查看 GPU 拓?fù)浣Y(jié)構(gòu) nvidia-smi topo -m # 查看 NVLink 狀態(tài)和帶寬 nvidia-smi nvlink -s # 查看 NVSwitch 相關(guān)信息如果支持 nvidia-smi nvlink -cnvidia-smi topo -m輸出的矩陣中行和列都是 GPU 編號(hào)交叉點(diǎn)表示兩塊 GPU 之間的連接類型。NV4表示 4 條 NVLink 連接NV6表示 6 條。對(duì)于 V100 NVSwitch 的配置應(yīng)該看到所有非對(duì)角線位置都是NV6。nvidia-smi nvlink -s會(huì)列出每條 NVLink 的速率和狀態(tài)正常應(yīng)該是 25.78125 Gbps per lanex8 lane 組成一條 NVLink。如果拓?fù)滹@示不對(duì)常見原因是驅(qū)動(dòng)版本不匹配或者 NVSwitch 固件需要更新。先檢查nvidia-smi輸出的驅(qū)動(dòng)版本和 CUDA 版本確保支持當(dāng)前硬件。NVSwitch 的管理端口走 PCIe可以用lspci確認(rèn)系統(tǒng)是否識(shí)別到交換芯片。3.3 NCCL 通信庫(kù)配置與帶寬測(cè)試硬件拓?fù)錄]問題之后下一步是驗(yàn)證實(shí)際通信帶寬。NCCL 是 NVIDIA 的集合通信庫(kù)支持 NVLink 和 NVSwitch 拓?fù)涓兄?。跑一個(gè) all-reduce 測(cè)試可以直觀看到帶寬表現(xiàn)。# 使用 nccl-tests 做 all-reduce 帶寬測(cè)試 # 假設(shè)已編譯 nccl-tests進(jìn)入 build 目錄 ./all_reduce_perf -b 8 -e 128M -f 2 -g 8 # 參數(shù)說(shuō)明 # -b 8 起始消息大小 8 字節(jié) # -e 128M 結(jié)束消息大小 128 MB # -f 2 消息大小倍增因子 # -g 8 使用 8 塊 GPU輸出中關(guān)注algbw算法帶寬和busbw總線帶寬。對(duì)于 NVSwitch 全互聯(lián)系統(tǒng)8 卡 all-reduce 的 busbw 應(yīng)該接近 NVLink 總帶寬的一半左右因?yàn)?all-reduce 本質(zhì)是每個(gè) GPU 發(fā)送和接收數(shù)據(jù)。如果 busbw 明顯低于預(yù)期檢查 NCCL 版本是否支持當(dāng)前架構(gòu)以及是否設(shè)置了NCCL_DEBUGINFO來(lái)查看拓?fù)渥R(shí)別日志。# 開啟 NCCL 調(diào)試日志 export NCCL_DEBUGINFO export NCCL_DEBUG_SUBSYSINIT,GRAPH # 然后重新跑測(cè)試觀察日志中是否識(shí)別到 NVSwitch日志里會(huì)打印 NCCL 選擇的通信路徑和算法。如果看到NVLS相關(guān)字樣說(shuō)明 NCCL 識(shí)別到了 NVSwitch 并使用了對(duì)應(yīng)的優(yōu)化路徑。如果只看到Ring或Tree且走 PCIe說(shuō)明拓?fù)渥R(shí)別有問題需要回頭檢查硬件連接或驅(qū)動(dòng)。4. 避坑與排查NVLink/NVSwitch 部署中的五個(gè)血淚教訓(xùn)4.1 現(xiàn)象nvidia-smi topo 顯示 GPU 間走 PCIe但硬件明明有 NVLink原因最常見的是驅(qū)動(dòng)版本太舊不認(rèn)識(shí) NVSwitch 拓?fù)?。另一個(gè)可能是 GPU 沒有正確插入 NVLink 橋接器對(duì)應(yīng)的插槽或者 BIOS 里 PCIe 配置限制了鏈路寬度。解決先升級(jí)驅(qū)動(dòng)到支持當(dāng)前 GPU 架構(gòu)的版本。然后檢查服務(wù)器主板手冊(cè)確認(rèn) GPU 插槽和 NVLink 橋接器的對(duì)應(yīng)關(guān)系。有些服務(wù)器需要特定插槽組合才能啟用 NVLink。最后進(jìn) BIOS 檢查 PCIe 鏈路寬度設(shè)置確保不是 x4 或 x8 降速運(yùn)行。4.2 現(xiàn)象NCCL 測(cè)試帶寬遠(yuǎn)低于理論值只有幾十 GB/s原因NCCL 可能沒有識(shí)別到 NVSwitch退回到了 PCIe 路徑?;蛘呦⒋笮≡O(shè)置不合理小消息下延遲主導(dǎo)帶寬上不去。解決設(shè)置NCCL_DEBUGINFO看日志確認(rèn)通信路徑。如果走 PCIe檢查nvidia-smi topo -m是否正常。消息大小方面all-reduce 測(cè)試從 8 字節(jié)到 128 MB 掃一遍看帶寬隨消息大小的變化曲線。通常 1 MB 以上才能看到接近峰值的帶寬。如果大消息帶寬也低檢查是否有多進(jìn)程爭(zhēng)搶 GPU 或者 ECC 顯存糾錯(cuò)開銷。4.3 現(xiàn)象多卡訓(xùn)練時(shí)隨機(jī)出現(xiàn) NCCL timeout 或 hang 住原因NVLink 鏈路不穩(wěn)定可能是信號(hào)完整性問題或者散熱導(dǎo)致芯片降頻。也可能是 NCCL 版本和 CUDA 版本不匹配通信算法選擇有 bug。解決先跑nvidia-smi nvlink -s看每條鏈路的誤碼率計(jì)數(shù)器。如果有鏈路誤碼率偏高檢查散熱和供電。軟件層面確保 NCCL 版本和 CUDA 版本對(duì)應(yīng)比如 CUDA 11.x 配 NCCL 2.8 以上。設(shè)置NCCL_IB_TIMEOUT和NCCL_IB_RETRY_CNT增加重試容忍度但這只是緩解根本問題還是要解決鏈路穩(wěn)定性。4.4 現(xiàn)象NVSwitch 芯片溫度過高系統(tǒng)降頻原因NVSwitch 功耗 100W被動(dòng)散熱依賴服務(wù)器風(fēng)道。如果風(fēng)道設(shè)計(jì)不好或者風(fēng)扇轉(zhuǎn)速策略保守芯片溫度會(huì)飆到降頻閾值。解決檢查服務(wù)器風(fēng)道是否按照 GPU 和 NVSwitch 的散熱需求設(shè)計(jì)。用nvidia-smi -q -d TEMPERATURE查看溫度。如果溫度持續(xù)偏高調(diào)整風(fēng)扇轉(zhuǎn)速策略或者增加輔助散熱。有些服務(wù)器 BIOS 里有風(fēng)扇曲線設(shè)置改成性能模式。4.5 現(xiàn)象升級(jí)驅(qū)動(dòng)后 NVSwitch 不識(shí)別系統(tǒng)只看到 GPU原因驅(qū)動(dòng)升級(jí)過程中 NVSwitch 固件沒有同步更新或者升級(jí)后沒有重啟導(dǎo)致固件版本不匹配。解決升級(jí)驅(qū)動(dòng)時(shí)確保包含 NVSwitch 固件組件。安裝完成后完全斷電重啟不是軟重啟。重啟后用lspci | grep -i nvidia確認(rèn)系統(tǒng)是否識(shí)別到 NVSwitch 設(shè)備。如果還是沒有檢查驅(qū)動(dòng)安裝日志里有沒有 NVSwitch 相關(guān)的錯(cuò)誤信息。5. 進(jìn)階技巧用 NVLink 感知的通信策略榨干多卡帶寬硬件拓?fù)鋵?duì)了NCCL 也識(shí)別到了 NVSwitch但實(shí)際訓(xùn)練速度還是沒達(dá)到預(yù)期這時(shí)候就得從通信策略上摳細(xì)節(jié)了。我一般會(huì)先確認(rèn) NCCL 是否真的用上了 NVSwitch 的全互聯(lián)能力而不是退回到 Ring 算法。Ring all-reduce 在 NVSwitch 全互聯(lián)拓?fù)湎缕鋵?shí)不是最優(yōu)的因?yàn)?Ring 的通信模式是順序傳遞沒有利用全交換的并行性。NCCL 在識(shí)別到 NVSwitch 后會(huì)優(yōu)先選擇 NVLSNVLink SHARP或者 Tree 算法這些算法能更好地利用交換架構(gòu)。# 強(qiáng)制指定 NCCL 算法做對(duì)比測(cè)試 export NCCL_ALGORing ./all_reduce_perf -b 8 -e 128M -f 2 -g 8 export NCCL_ALGOTree ./all_reduce_perf -b 8 -e 128M -f 2 -g 8 # 如果支持 NVLS觀察日志中是否出現(xiàn) NVLS 字樣 export NCCL_ALGONVLS ./all_reduce_perf -b 8 -e 128M -f 2 -g 8對(duì)比不同算法下的 busbw通常 NVLS 或 Tree 在全互聯(lián)拓?fù)湎卤?Ring 高 20% 到 30%。如果 NVLS 不可用檢查 NCCL 版本是否支持以及 GPU 架構(gòu)是否在支持列表里。Hopper 架構(gòu)對(duì) NVLS 的支持最完整Ampere 次之Volta 可能只有部分支持。另一個(gè)容易忽略的點(diǎn)是通信和計(jì)算的 overlap。在訓(xùn)練循環(huán)里梯度同步可以和反向傳播重疊執(zhí)行。PyTorch 的 DDP 默認(rèn)會(huì)做 overlap但如果模型結(jié)構(gòu)特殊或者梯度 bucket 設(shè)置不合理overlap 效果會(huì)打折扣。調(diào)整bucket_cap_mb參數(shù)可以控制梯度分桶大小太小會(huì)導(dǎo)致通信頻繁啟動(dòng)太大則 overlap 窗口不夠。# PyTorch DDP 初始化時(shí)調(diào)整 bucket 大小 import torch.distributed as dist from torch.nn.parallel import DistributedDataParallel as DDP dist.init_process_group(backendnccl) model DDP(model, device_ids[local_rank], bucket_cap_mb25) # bucket_cap_mb 默認(rèn) 25MB根據(jù)模型參數(shù)量和 NVLink 帶寬調(diào)整 # 參數(shù)量大、NVLink 帶寬高時(shí)可以適當(dāng)增大減少通信次數(shù)驗(yàn)證 overlap 是否生效可以用 PyTorch profiler 抓一段訓(xùn)練 trace看通信 kernel 和計(jì)算 kernel 在時(shí)間軸上是否重疊。如果通信 kernel 之間有大段空隙說(shuō)明 overlap 沒做好需要調(diào)整 bucket 大小或者檢查是否有同步點(diǎn)阻塞了流水線。從那以后我每次搭多卡環(huán)境都強(qiáng)制走一遍nvidia-smi topo -m→ NCCL 帶寬測(cè)試 → profiler 抓 overlap 這三步確認(rèn)硬件拓?fù)?、通信?kù)配置和實(shí)際執(zhí)行效率都對(duì)得上。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取