練的核心通信算法與優(yōu)化實踐)
1. 項目概述為什么Allreduce是大模型訓(xùn)練的“生命線”如果你最近關(guān)注過任何關(guān)于大模型訓(xùn)練的技術(shù)討論或者嘗試過自己動手微調(diào)一個哪怕只有幾十億參數(shù)的模型一個詞一定會高頻出現(xiàn)分布式訓(xùn)練。而當(dāng)你真正開始部署多張顯卡準(zhǔn)備讓它們協(xié)同工作時另一個詞會立刻成為你繞不開的“攔路虎”或“救世主”——Allreduce。這聽起來像是一個神秘的咒語但它實際上是大模型時代讓算力從“單打獨斗”走向“軍團作戰(zhàn)”的核心通信算法。沒有它我們今天談?wù)摰那|、萬億參數(shù)大模型可能還停留在實驗室的紙面構(gòu)想上。簡單來說Allreduce解決了一個在分布式訓(xùn)練中最基礎(chǔ)也最要命的問題如何高效、準(zhǔn)確地將所有計算節(jié)點比如多張GPU上的局部計算結(jié)果通常是梯度匯總起來計算出一個全局一致的結(jié)果再同步回所有節(jié)點這個過程就是模型參數(shù)更新的依據(jù)。想象一下你有一個由100位專家組成的團隊每人都獨立研究同一課題的一部分每天結(jié)束時你們需要把所有人的發(fā)現(xiàn)匯總、取平均形成一份統(tǒng)一的報告第二天大家再基于這份報告繼續(xù)研究。Allreduce就是這個“高效開會并同步結(jié)論”的機制。如果這個機制效率低下或者出錯那么團隊協(xié)作的優(yōu)勢將蕩然無存甚至不如一個人單干。隨著模型參數(shù)規(guī)模指數(shù)級增長單張顯卡的顯存和算力早已捉襟見肘。分布式訓(xùn)練從“可選項”變成了“必選項”。而Allreduce的性能直接決定了你的多卡集群是“112”還是“111”。通信開銷一旦成為瓶頸昂貴的GPU大部分時間都在等待數(shù)據(jù)同步算力利用率慘不忍睹。因此深入理解Allreduce不僅僅是學(xué)習(xí)一個算法更是掌握了一把優(yōu)化大模型訓(xùn)練效率、降低訓(xùn)練成本的關(guān)鍵鑰匙。無論是使用PyTorch的DistributedDataParallel還是DeepSpeed、Colossal-AI等高級框架其底層通信的基石之一就是各種優(yōu)化過的Allreduce實現(xiàn)。2. Allreduce核心原理從樸素想法到高效實現(xiàn)要理解Allreduce為什么重要以及如何優(yōu)化我們得先回到問題本源。假設(shè)我們有N個并行進程通常對應(yīng)N張GPU每個進程i都有一個相同大小的數(shù)據(jù)塊比如模型梯度的一部分A_i。Allreduce的目標(biāo)是對所有進程的A_i應(yīng)用一個歸約操作如求和、求平均、求最大值然后將最終結(jié)果B A_0 op A_1 op ... op A_{N-1}寫回到每一個進程的內(nèi)存中。2.1 最樸素的實現(xiàn)中央聚合與廣播一個最直觀的想法是指定一個進程比如Rank 0作為“領(lǐng)導(dǎo)”。所有其他進程把自己的數(shù)據(jù)A_i發(fā)送給領(lǐng)導(dǎo)。領(lǐng)導(dǎo)收集齊所有數(shù)據(jù)后執(zhí)行歸約操作得到B然后再把B廣播給所有其他進程。這個過程看似簡單但存在明顯瓶頸通信瓶頸領(lǐng)導(dǎo)進程Rank 0的通信帶寬會成為整個系統(tǒng)的瓶頸。它需要接收N-1份數(shù)據(jù)再發(fā)送N-1份結(jié)果。網(wǎng)絡(luò)鏈路很容易被塞滿。單點風(fēng)險領(lǐng)導(dǎo)進程一旦故障或負(fù)載過高整個訓(xùn)練過程就會停滯。資源浪費其他進程的通信能力在大部分時間里是閑置的。這種模式在學(xué)術(shù)上被稱為“樸素的Allreduce”或“中央歸約-廣播”在實際的大規(guī)模訓(xùn)練中極少使用因為它無法有效利用集群的總通信帶寬。2.2 經(jīng)典算法Ring-Allreduce為了解決樸素方法的瓶頸業(yè)界廣泛采用了一種更優(yōu)雅、能充分利用每個節(jié)點雙向帶寬的算法——Ring-Allreduce。它通過將N個進程邏輯上組織成一個環(huán)Ring讓數(shù)據(jù)像接力賽一樣在環(huán)中流動分步完成歸約和廣播。Ring-Allreduce將總數(shù)據(jù)量M平均分成N個塊Scatter-Reduce階段然后再次在環(huán)中傳遞完成廣播Allgather階段。假設(shè)有4個GPUP0, P1, P2, P3數(shù)據(jù)總量為M。第一階段Scatter-Reduce目標(biāo)是讓每個GPU最終擁有一個全局歸約后的數(shù)據(jù)塊。P0將它的第1塊數(shù)據(jù)發(fā)給P1同時接收P3發(fā)來的第4塊數(shù)據(jù)。每個GPU在接收到一個數(shù)據(jù)塊后立即將其與本地對應(yīng)的數(shù)據(jù)塊進行歸約如累加。經(jīng)過N-1步本例為3步后每個GPU上都恰好有一個完整歸約后的數(shù)據(jù)塊。例如P0擁有所有GPU第0塊數(shù)據(jù)的和P1擁有所有GPU第1塊數(shù)據(jù)的和以此類推。第二階段Allgather目標(biāo)是將每個GPU上歸約好的那個數(shù)據(jù)塊廣播給所有其他GPU使得每個GPU都擁有完整的全局歸約結(jié)果B。P0將它現(xiàn)在擁有的已歸約的第0塊數(shù)據(jù)發(fā)給P1同時從P3接收第3塊數(shù)據(jù)。每個GPU在接收到一個數(shù)據(jù)塊后將其存入本地對應(yīng)位置。同樣經(jīng)過N-1步后每個GPU都擁有了全部N個歸約后的數(shù)據(jù)塊即完整的B。Ring-Allreduce的優(yōu)勢帶寬最優(yōu)在每一步中每個GPU都在同時發(fā)送和接收數(shù)據(jù)充分利用了雙向帶寬。理論上對于大消息其有效帶寬接近于單個鏈路的帶寬。無單點瓶頸所有GPU角色對等沒有中心節(jié)點系統(tǒng)擴展性更好。通信量固定總通信數(shù)據(jù)量約為2*(N-1)/N * M當(dāng)N較大時趨近于2M。這比樸素算法的2(N-1)M要小得多。Ring-Allreduce的劣勢延遲與步數(shù)完成整個操作需要2*(N-1)步每一步都有通信延遲。當(dāng)GPU數(shù)量N很大時完成時間受限于環(huán)的周長。因此對于小消息延遲開銷占比大效率不高。容錯性環(huán)中任何一個節(jié)點故障會導(dǎo)致整個通信鏈斷裂。實操心得在NVIDIA的NGC容器或大多數(shù)深度學(xué)習(xí)框架的分布式環(huán)境中默認(rèn)的Allreduce實現(xiàn)通常就是基于Ring-Allreduce的優(yōu)化版本如NCCL庫。當(dāng)你用4卡或8卡訓(xùn)練時感覺通信開銷不大但一旦擴展到32卡、64卡甚至更多就需要密切關(guān)注環(huán)的拓?fù)浣Y(jié)構(gòu)是否最優(yōu)比如是否都在同一個物理節(jié)點內(nèi)跨節(jié)點的鏈路帶寬是否均衡否則延遲會顯著增加。2.3 其他優(yōu)化算法Tree-Allreduce與雙樹算法除了Ring另一種常見模式是Tree-Allreduce樹形歸約。它像一場錦標(biāo)賽每兩個葉子節(jié)點GPU將數(shù)據(jù)歸約到它們的父節(jié)點父節(jié)點之間再繼續(xù)歸約最終到達(dá)根節(jié)點。然后結(jié)果再從根節(jié)點廣播回所有葉子節(jié)點。優(yōu)勢對于中等大小的消息和節(jié)點數(shù)樹形結(jié)構(gòu)的步數(shù)約為2*log?(N)比Ring的2*(N-1)在N很大時小得多因此延遲可能更低。劣勢根節(jié)點及其父節(jié)點在歸約和廣播階段容易成為帶寬瓶頸因為上層節(jié)點需要處理更多子節(jié)點的數(shù)據(jù)流量。為了結(jié)合Ring和Tree的優(yōu)點出現(xiàn)了雙樹算法等變種。在實際的高性能計算庫中如NVIDIA的NCCLNVIDIA Collective Communication Library或Intel的oneCCL它們會根據(jù)集群的實際拓?fù)銷VLink連接、PCIe交換機、InfiniBand網(wǎng)絡(luò)、消息大小和GPU數(shù)量動態(tài)選擇或混合使用多種算法以達(dá)到最優(yōu)性能。例如在同一個DGX服務(wù)器內(nèi)的8張GPU之間可能采用基于NVLink的定制化高速算法在跨多臺服務(wù)器的GPU之間則可能采用適應(yīng)網(wǎng)絡(luò)拓?fù)涞臉湫位颦h(huán)形算法。3. 實操在PyTorch分布式訓(xùn)練中觀察與使用Allreduce理論說了很多我們直接上手看看在最常見的PyTorch分布式數(shù)據(jù)并行DDP訓(xùn)練中Allreduce是如何工作的以及我們?nèi)绾胃兄陀绊懰?.1 DDP背后的Allreduce當(dāng)你使用torch.nn.parallel.DistributedDataParallel包裝模型時PyTorch在背后自動為你處理了梯度同步。其基本流程在每個訓(xùn)練迭代iteration中如下前向傳播每個GPU用自己的數(shù)據(jù)副本計算損失。反向傳播每個GPU獨立計算梯度。此時每個GPU上的梯度是局部梯度基于它看到的mini-batch數(shù)據(jù)。梯度同步這是Allreduce登場的時候。所有GPU上的局部梯度會通過Allreduce操作默認(rèn)是求和進行同步使得每個GPU都獲得全局平均梯度如果Allreduce用的是求和DDP會在內(nèi)部除以進程總數(shù)world_size來得到平均。參數(shù)更新每個GPU使用同步后的全局梯度獨立地更新其模型參數(shù)。由于初始參數(shù)和梯度都一致更新后的參數(shù)在所有GPU上仍然保持一致。這個過程對用戶是透明的你只需要啟動分布式進程DDP就會搞定通信。3.2 代碼示例手動觸發(fā)一個Allreduce為了更清晰地理解我們可以繞過DDP手動使用PyTorch的分布式通信原語dist.all_reduce來演示。import torch import torch.distributed as dist import os def run_allreduce_example(): # 初始化進程組。實際中這通常由 torch.distributed.launch 或 torchrun 設(shè)置。 # 這里假設(shè)環(huán)境變量已配置好。 dist.init_process_group(backendnccl) # 使用NCCL后端對GPU通信最優(yōu) rank dist.get_rank() world_size dist.get_world_size() # 每個進程創(chuàng)建一個張量值是其rank1 tensor torch.ones(2, 3).cuda() * (rank 1) print(fRank {rank} before all_reduce: {tensor}) # 執(zhí)行Allreduce操作操作為求和dist.ReduceOp.SUM dist.all_reduce(tensor, opdist.ReduceOp.SUM) # 注意此時 tensor 已經(jīng)被就地in-place修改了 print(fRank {rank} after all_reduce (SUM): {tensor}) # 如果我們想要的是平均值可以再除以 world_size # 或者PyTorch 1.14 支持 dist.ReduceOp.AVG但需要后端支持。 # tensor.div_(world_size) # print(fRank {rank} after averaging: {tensor}) if __name__ __main__: # 實際運行需要多進程啟動器例如 # python -m torch.distributed.launch --nproc_per_node4 your_script.py run_allreduce_example()運行這個程序需要真正的分布式環(huán)境你會看到假設(shè)有4個進程rank 0~3每個進程的初始張量分別為全1、全2、全3、全4。執(zhí)行all_reduce求和后每個進程的張量都變成了全101234。這就是Allreduce的“All”結(jié)果分發(fā)到所有節(jié)點和“reduce”歸約求和效果。3.3 關(guān)鍵參數(shù)與后端選擇在dist.init_process_group中backend參數(shù)至關(guān)重要它決定了使用什么通信庫來實現(xiàn)Allreduce等集合通信操作ncclNVIDIA GPU的首選。針對NVIDIA GPU和NVLink/InfiniBand進行了深度優(yōu)化在GPU間通信效率最高。gloo一個由Facebook開發(fā)的通信庫支持CPU和GPU通過CUDA。在CPU上進行分布式訓(xùn)練或者某些GPU通信的故障排查時可以用它。通常性能不如NCCL。mpi使用傳統(tǒng)的MPIMessage Passing Interface實現(xiàn)。通常在超算環(huán)境中與特定硬件綁定使用。對于絕大多數(shù)基于NVIDIA GPU的大模型訓(xùn)練backendnccl是不二之選。注意事項在分布式訓(xùn)練腳本中確保在每個進程里需要Allreduce的張量都位于GPU上并且是連續(xù)的contiguous。非連續(xù)張量可能會觸發(fā)隱式的內(nèi)存拷貝影響性能。使用tensor.contiguous()可以確保這一點。4. 性能調(diào)優(yōu)與高級話題讓Allreduce飛起來理解了基本原理和基礎(chǔ)用法后如何讓Allreduce在實際訓(xùn)練中更快就成了核心工程問題。通信優(yōu)化往往能帶來顯著的訓(xùn)練加速。4.1 通信與計算重疊這是分布式訓(xùn)練優(yōu)化的“圣杯”。理想狀態(tài)下GPU在計算前向/反向傳播的同時能利用空閑的網(wǎng)絡(luò)資源進行梯度通信。PyTorch DDP通過梯度桶Gradient Bucketing機制來實現(xiàn)這一點。原理DDP不會等到所有梯度都計算完畢后才一次性發(fā)起Allreduce。相反它將模型參數(shù)分組到多個“桶”中。當(dāng)一個桶內(nèi)的所有梯度都計算完成時就立即對這個桶的梯度發(fā)起異步Allreduce。這樣通信操作可以與后續(xù)層的反向傳播計算重疊。調(diào)整桶的大小可以通過bucket_cap_mb參數(shù)來調(diào)整。默認(rèn)值25MB是一個較好的起點。對于模型參數(shù)極多、層數(shù)很深的情況適當(dāng)調(diào)小桶大小可能增加重疊機會但也會增加通信次數(shù)和小包開銷需要根據(jù)實際profile結(jié)果調(diào)整。model torch.nn.parallel.DistributedDataParallel( model, device_ids[local_rank], output_devicelocal_rank, bucket_cap_mb25, # 可以嘗試調(diào)整為15或50 )4.2 梯度壓縮與稀疏化對于超大模型即使梯度是16位浮點數(shù)FP16通信量依然巨大。梯度壓縮技術(shù)旨在減少需要傳輸?shù)臄?shù)據(jù)量。梯度裁剪Gradient Clipping雖然主要用來穩(wěn)定訓(xùn)練但間接減少了梯度值的動態(tài)范圍有時能提高壓縮效率。FP16/BF16混合精度訓(xùn)練這已經(jīng)是標(biāo)配。使用像torch.cuda.amp這樣的自動混合精度模塊在前向和反向時使用BF16/FP16在優(yōu)化器更新時使用FP32主副本。這直接將通信量減半。更激進的壓縮8位量化將梯度量化為8位整數(shù)進行傳輸接收端再反量化。如DeepSpeed的ZeroQuant。稀疏化只傳輸絕對值大于某個閾值的梯度Top-k梯度。這能極大減少通信量但需要更復(fù)雜的算法來保證收斂性如深度梯度壓縮Deep Gradient Compression。錯誤反饋在壓縮通信中將本輪壓縮誤差累積到下一輪保證長期收斂精度。這是許多高級壓縮算法的核心。這些技術(shù)通常集成在DeepSpeed、Colossal-AI等高級框架中普通DDP用戶無需手動實現(xiàn)但了解其原理有助于選擇配置。4.3 拓?fù)涓兄ㄐ旁谟啥嗯_服務(wù)器組成的集群中GPU之間的物理連接速度差異很大。同一臺服務(wù)器內(nèi)通過NVLink互聯(lián)的GPU帶寬可能高達(dá)數(shù)百GB/s而跨服務(wù)器通過InfiniBand或以太網(wǎng)連接的GPU帶寬可能只有幾十GB/s。NCCL這樣的庫是拓?fù)涓兄乃鼤L試構(gòu)建一個通信環(huán)或樹使得快速鏈路如NVLink承擔(dān)更多的內(nèi)部通信慢速鏈路只用于必要的跨節(jié)點通信從而最小化整體通信時間。作為用戶我們需要做的是在硬件上確保服務(wù)器內(nèi)GPU通過NVLink全互聯(lián)服務(wù)器間使用高速網(wǎng)絡(luò)如InfiniBand。在軟件上正確設(shè)置NCCL_SOCKET_IFNAME環(huán)境變量來指定高速網(wǎng)卡或使用NCCL_DEBUGINFO來觀察NCCL選擇的通信路徑是否合理。4.4 Allreduce vs. Reduce-Scatter Allgather在諸如PyTorch的FSDPFully Sharded Data Parallel或DeepSpeed的ZeRO-3等模型并行策略中Allreduce被拆解成了更細(xì)粒度的組合操作Reduce-Scatter和Allgather。Reduce-Scatter每個進程持有一份完整的參數(shù)或梯度。操作后每個進程只持有全局歸約結(jié)果的一個分片。這相當(dāng)于Allreduce的“Scatter-Reduce”階段但結(jié)果不廣播。Allgather每個進程持有一個數(shù)據(jù)分片。操作后每個進程收集所有其他進程的分片拼成完整數(shù)據(jù)。FSDP在前向和反向傳播中通過精巧地安排Reduce-Scatter和Allgather的時機只在需要時才將參數(shù)聚合到單個GPU上從而將顯存占用分?jǐn)偟剿蠫PU上實現(xiàn)了超大規(guī)模模型的訓(xùn)練。可以說理解了Allreduce是理解這些更高級并行策略的基礎(chǔ)。5. 常見問題排查與調(diào)試技巧在實際部署中Allreduce相關(guān)的問題常常表現(xiàn)為訓(xùn)練速度慢、卡死或報錯。5.1 性能問題排查清單現(xiàn)象可能原因排查方法訓(xùn)練迭代時間遠(yuǎn)長于理論計算時間通信成為瓶頸1. 使用NCCL_DEBUGINFO和NCCL_DEBUG_SUBSYSCOLL查看通信耗時。2. 用PyTorch Profiler或Nsight Systems進行性能分析觀察all_reduce操作在時間線上的占比。多機訓(xùn)練時速度極慢網(wǎng)絡(luò)帶寬不足或延遲高拓?fù)浞亲顑?yōu)1. 檢查節(jié)點間網(wǎng)絡(luò)帶寬如使用ib_write_bw測試InfiniBand。2. 檢查NCCL_SOCKET_IFNAME是否指向了正確的高速網(wǎng)卡。3. 嘗試調(diào)整NCCL_ALGO環(huán)境變量如設(shè)置為Tree或Ring強制使用某種算法。小規(guī)模2-4卡訓(xùn)練通信開銷也很大消息太小延遲主導(dǎo)或使用了非最優(yōu)后端1. 確保使用backendnccl。2. 檢查是否有大量頻繁的小張量Allreduce考慮進行梯度聚合。3. 對于CPU訓(xùn)練gloo后端對小消息可能更好。訓(xùn)練過程中出現(xiàn)間歇性卡頓或超時網(wǎng)絡(luò)不穩(wěn)定某個節(jié)點負(fù)載過高導(dǎo)致響應(yīng)慢1. 增加NCCL_BLOCKING_WAIT或調(diào)整NCCL_TIMEOUT來觀察超時點。2. 檢查集群監(jiān)控看是否有節(jié)點CPU、內(nèi)存或IO爆滿。3. 使用NCCL_DEBUGWARN查看警告信息。5.2 NCCL環(huán)境變量調(diào)優(yōu)實戰(zhàn)NCCL提供了豐富的環(huán)境變量進行調(diào)優(yōu)。以下是一些常用且安全的調(diào)優(yōu)選項可以在啟動訓(xùn)練腳本前設(shè)置# 啟用NCCL調(diào)試信息級別從INFO到WARN到ERROR export NCCL_DEBUGINFO # 更詳細(xì)的子系統(tǒng)調(diào)試如COLL集合通信、NET網(wǎng)絡(luò)、GRAPH拓?fù)?export NCCL_DEBUG_SUBSYSCOLL,GRAPH # 強制使用特定的通信算法默認(rèn)為空NCCL自動選擇。在算法選擇不當(dāng)時可嘗試 # export NCCL_ALGORing # export NCCL_ALGOTree # 設(shè)置用于通信的網(wǎng)絡(luò)接口。在多網(wǎng)卡環(huán)境中至關(guān)重要 # 使用 ifconfig 或 ip addr 查看你的高速網(wǎng)卡名如ib0, eth1 export NCCL_SOCKET_IFNAMEeth1 # 調(diào)整單個NCCL操作的超時時間單位秒在網(wǎng)絡(luò)不穩(wěn)定時可能需要增加 export NCCL_TIMEOUT180 # 對于PCIe拓?fù)鋸?fù)雜的系統(tǒng)嘗試關(guān)閉PCIe重排序有時能解決死鎖 export NCCL_P2P_DISABLE1 # 慎用這會禁用GPU間的直接通信P2P # export NCCL_P2P_LEVELLOC # 或嘗試限制P2P級別重要提示修改這些環(huán)境變量前最好在測試任務(wù)上驗證。特別是NCCL_P2P_DISABLE和NCCL_ALGO不恰當(dāng)?shù)脑O(shè)置可能導(dǎo)致性能嚴(yán)重下降。5.3 一個典型的死鎖問題排查場景在混合使用模型并行手動切分模型到不同GPU和數(shù)據(jù)并行DDP的復(fù)雜訓(xùn)練腳本中程序偶爾會卡死日志停在某個Allreduce操作。排查思路檢查進程同步確保所有進程都執(zhí)行到了Allreduce的同一位置??梢栽贏llreduce前后添加dist.barrier()和打印語句來定位。檢查張量形狀與設(shè)備確保所有進程上需要Allreduce的張量形狀完全一致并且都位于相同的設(shè)備類型如都是CUDA上。一個進程張量在CPU另一個在GPU必然導(dǎo)致死鎖或錯誤。檢查非確定性操作如果前向傳播中存在非確定性操作如dropout沒有設(shè)置固定隨機種子可能導(dǎo)致不同進程的計算圖有細(xì)微差別進而使得需要同步的梯度張量列表或順序出現(xiàn)分歧引發(fā)死鎖。確保使用model.train()時為每個進程設(shè)置相同的隨機種子torch.manual_seed(seed rank)可能不夠需要更細(xì)粒度的控制。簡化復(fù)現(xiàn)嘗試創(chuàng)建一個最小的、能復(fù)現(xiàn)問題的代碼片段。通常在這個過程中你自己就能發(fā)現(xiàn)錯誤所在。根本原因很多時候這類死鎖源于進程間控制流不一致。例如某個進程因為數(shù)據(jù)異常提前退出訓(xùn)練循環(huán)而其他進程還在執(zhí)行Allreduce就會永遠(yuǎn)等待那個退出的進程。使用torch.distributed的彈性訓(xùn)練如torchrun可以更好地處理這類故障但最根本的還是在代碼中做好異常處理和日志記錄確保所有進程同進同退。6. 超越Allreduce新一代集合通信與硬件趨勢雖然Allreduce是當(dāng)前基石但硬件和算法的演進正在催生新的可能性。異步Allreduce在部分研究中為了進一步隱藏通信延遲嘗試讓計算和通信完全解耦進行“有延遲”的梯度更新。但這會引入收斂穩(wěn)定性的挑戰(zhàn)需要更復(fù)雜的算法來校正。All-to-All通信在更復(fù)雜的模型并行如Transformer中的序列并行或MoE混合專家模型中通信模式可能從Allreduce變?yōu)锳ll-to-All即每個進程都需要向所有其他進程發(fā)送不同的數(shù)據(jù)分片。這對網(wǎng)絡(luò)硬件提出了更高的要求也催生了新的拓?fù)涓兄惴?。定制化硬件NVIDIA的NVLink和InfiniBand已經(jīng)是高性能分布式訓(xùn)練的標(biāo)配。未來更緊密的芯片間互聯(lián)如NVIDIA的NVSwitch、Grace Hopper超級芯片、光互聯(lián)技術(shù)、甚至存算一體架構(gòu)將從硬件層面根本性地降低通信開銷。與之配套的是通信庫如NCCL需要持續(xù)優(yōu)化以榨干硬件性能。算法與通信的協(xié)同設(shè)計這或許是終極方向。像ZeRO、FSDP這樣的策略已經(jīng)不僅僅是優(yōu)化通信而是重新設(shè)計了模型狀態(tài)在內(nèi)存中的分布方式使得必要的通信量最小化。未來從模型架構(gòu)設(shè)計之初就考慮分布式特性可能會成為大模型訓(xùn)練的常態(tài)。理解Allreduce是踏入大規(guī)模人工智能系統(tǒng)優(yōu)化領(lǐng)域的第一步。它連接了算法、軟件框架和硬件體系。當(dāng)你下次看到訓(xùn)練任務(wù)中GPU利用率波動或者嘗試將訓(xùn)練擴展到上百張顯卡時希望你能想起這個在背后默默工作的“同步引擎”并知道如何去觀察它、優(yōu)化它。畢竟在這個算力即生產(chǎn)力的時代讓每一塊GPU都滿負(fù)荷運轉(zhuǎn)是每一位算法工程師和系統(tǒng)工程師的職責(zé)所在。