隨著 AI 訓練規模的擴大,單個數據中心 (DC) 不足以提供所需的計算能力。應對這一挑戰的最新方法依賴于多個數據中心位于同一地點或分布在不同地理位置。在最近的一項開源功能中,NVIDIA 集合通信庫 (NCCL) 現在能夠跨多個數據中心無縫通信,同時考慮網絡拓撲結構,以確保提供最佳性能。
下面我們將介紹所提議方法的內部運作方式,以及實現預期功能所需的關鍵關注點。
NCCL 已經支持多個通信器,每個通信器都依賴于不同的網絡。例如,用戶可以使用內部 DC 網絡將全局歸約集合組成內部 DC 歸約散射,然后在內部 DC 網絡上執行全局歸約,并在內部 DC 網絡上執行最終的全局收集。此方法已在 NVIDIA Nemo 框架中使用。
NCCL 中提議的交叉 DC 功能有兩個目標。首先,我們保證在多直流連接的情況下提供最佳性能。其次,我們支持多直流通信,對 AI 訓練工作負載的修改最少。
具體來說,對于此功能,我們針對兩種連接場景 (請參見下圖 1) :
- 通過同構網絡連接的不同數據中心 (對于 DC 內和 DC 間網絡,通常為 IB 或 RoCE) 。
- 數據中心通過異構網絡連接。通常,InfiniBand (IB) 或 RDMA over Converged Ethernet (RoCE) 用于 DC 內連接,TCP 用于 DC 間網絡。
在這兩個場景中,我們在下面詳細介紹了如何在 NCCL 中使用跨 DC 功能,以及在評估性能時需要牢記的一些關鍵性能注意事項。

NCCL 中的網絡拓撲感知
網絡通過 ncclNet
API 暴露給 NCCL。每個 ncclNet
都對應一組連接到同一網絡的虛擬設備 (以及用于與該組設備交互的關聯 API) 。從 NCCL 的角度來看,暴露在兩個不同網絡上的兩臺設備將被視為兩個斷開連接的網絡的一部分。我們還注意到,合作伙伴和網絡提供商可以自由地公開與單個或多個 ncclNet
結構相同的物理網絡。
這種抽象是關鍵,因為它提供了支持跨 DC 通信的構建塊。在本文檔的其余部分中,“網絡”旨在表示為 ncclNet
。
第 1 步:啟用多個網絡
要允許 NCCL 使用多個網絡 (多個 ncclNet
) ,必須設置 NCCL_ALLNET_ENABLE=1
。當 NCCL_ALLNET_ENABLE
設置為 1 時,NCCL 將嘗試為每個通信器加載所有 ncclNet
插件。副作用是,它會禁用 collNet
。將值設置為 0
(默認) 將恢復已知行為:NCCL 將僅使用第一個成功加載的插件。
如前所述,NCCL 假設來自不同網絡的設備斷開連接。雖然在異構網絡場景中,此假設可能足以推理網絡拓撲,但在單個同構網絡的情況下,此假設是不夠的 (請參見圖 1) 。為了更深入地了解網絡拓撲,我們引入了網絡 ID 的概念。
第 2 步:NCCL 通過網絡 ID 發現網絡拓撲
拓撲感知依賴于 fabricId
,它捕獲拓撲信息和設備之間的連接。使用 fabricId
,NCCL 查詢屬于同一 tg_ 13 的兩臺網絡設備之間的網絡拓撲和其他路徑信息。NCCL 分兩步探索網絡拓撲:
- 在初始化過程中,系統會交換通信器中每個秩可用的
fabricId
列表。對于 NCCL,fabricId
是不透明的 64 位句柄。fabricId
由網絡插件提供,其確切含義取決于插件的實現。 - 建立連接時,NCCL 將使用新添加到
ncclNet
:tg_ 18 的 API 來查詢網絡連接。在此功能的特定環境中,path
信息僅包含兩個以參數形式給出的fabricId
之間的連接情況:NET_LOC_DCL0 用于內部 DC 連接,NET_ LOC_ DCL1 用于跨 DC 連接,NET_ LOC_ DISC 用于斷開連接的 tg_ 21。
解釋 fabricId
之間的連接是網絡插件的責任。實現此目的的方法有很多,例如使用 64 位哈希主機名和利用 SLURM 拓撲文件。
在 NCCL IB 插件實現中,我們選擇了一種更簡單的方法。通過環境變量 NCCL_IB_HCA
以 tg_ 25 格式設置 tg_ 23。fabricId
的值應為 tg_ 27 之前的正整數,并解釋為 tg_ 28,其中 tg_ 29 可以使用 NCCL_IB_FABRICID_MAXRAIL
設置。如果未設置,每個 fabricId
值將被解釋為 tg_ 32 (即 tg_ 33 和 tg_ 34) 。具有不同 RAIL_ID
的設備將被解釋為斷開連接,而不管它們的 tg_ 36 如何。具有相同 RAIL_ID
和相同 tg_ 38 的設備將被解釋為 tg_ 39,具有相同 RAIL_ID
和 differenttg_ 41 的設備將被設置為 tg_ 42。
第 3 步:網絡拓撲引導算法
NCCL 包含三種算法系列:Ring
、tg_ 44 (以及 tg_ 45 等變體) 和 tg_ 46。這些算法支持不同類型的群集和通信模式。在跨 DC 通信方面,我們重點研究了 Ring
和 tg_ 48 算法的更稀疏通信模式。下文詳細介紹的所有更改均旨在實現兩個目標: (1) 盡可能避免跨越 (通常較慢的) DC 間鏈路。(2) 利用盡可能多的網絡設備進行 DC 間連接。后者在異構網絡的用例中尤為重要,其中 DC 間連接的帶寬和一般性能明顯低于 DC 內連接。
環形算法
為避免多個 DC 間連接,我們在每個 DC 內優先重新排序。然后,打開每個環,并使用兩個松散的一端將 DC 連接在一起。通過這種方法,我們可以保證跨 DC 連接的數量為 2*(nDc-1)
,其中 nDc
是 DC 的數量。
對于異構網絡,即使采用后一種方法,單個 DC 間設備也將成為整個集合性能的瓶頸 (請參見圖 2) 。NCCL 會創建多個環 (圖中有四個環) ,其中所有環都會在同一組節點之間通過直流連接。為了減輕這種影響,我們引入了散射 (通過 NCCL_SCATTER_XDC=1
啟用) ,其中每個環將使用兩個不同的節點通過直流連接。
性能提升是巨大的。例如,如果通信器每個節點包含四個 GPU (每個 GPU 具有 400 Gbps HCA) ,則單個跨直流連接必須提供 1.6 Tbps。啟用散射后,對跨直流連接的要求降低到 400 Gbps;在實踐中,通過增加每個 HCA 的通道數,以及使用的跨直流連接數,可以進一步降低這一要求。這種解釋故意忽略了許多細節,例如選擇通道數量和相關協議。盡管它不準確,但在啟用散射時,它可以對信道行為提供強烈的直覺。

樹算法
與環算法方法非常相似,這里的目標是避免跨 DC 連接的次數超過實際需要的次數,并允許散射將樹分散到多個設備上,以避免出現單個設備瓶頸。我們首先在每個 DC 內構建樹。由于 NCCL 構建樹的方式,我們確定每個根都有一個空的子插槽和一個空的父插槽。這允許我們將每個 DC 的每棵樹的根鏈接在一起,以便構建覆蓋所有 DC 的全局樹。新樹的深度在 DC 數量上是線性的,在每個 DC 的節點數上是對數的。假設每個 DC 的節點數量恒定,我們獲得的深度為 (nDC - 1) + log2(nNodes)
。
通道散射的實現方式與環算法類似。樹根是跨 DC 的實際通信對象,因此我們將它們分散在可用節點之間。這使得 NCCL 能夠利用更多跨 DC 的連接,并消除潛在的瓶頸。
性能注意事項
DC 之間的連接質量可能會提升應用的整體性能。量化成對連接的性能非常重要,這樣才能推斷出 NCCL_SCATTER_XDC
和 tg_ 55 的正確值。第一種方法將實現通道在多個設備之間的散射,而第二種方法則用于控制 NCCL 將使用的通道數量。
以下是可能對跨直流連接達到峰值性能至關重要的各種參數的非詳盡列表:
NCCL_IB_QPS_PER_CONNECTION
用于更高延遲的 IB/ RoCE 連接。NCCL_NSOCKS_PERTHREAD
和 tg_ 58 用于更高延遲的 TCP 連接。NCCL_SOCKET_INLINE
和NCCL_SOCKET_MIN_TASKSIZE
用于控制 TCP 消息大小和內聯數據大小。NCCL_BUFFSIZE
允許 NCCL 發送更大的消息。
總結
在最近的一項研究中,NCCL 支持在兩個關鍵連接場景中跨多個 DC 的無縫集合通信。第一種是同構情況,即單個網絡為 DC 間和 DC 內提供連接。其次是異構情況,其中使用不同的網絡 (以及相應的技術) 來連接節點內部 DC 和內部 DC。
但是,我們發現對多個網絡的支持不足以為 NCCL 提供足夠的拓撲感知能力,因此無法提供最佳性能。為了填補這一空白,我們引入了 fabricID 以及新的 ncclNet API。這使得 NCCL 能夠查詢詳細的網絡拓撲,并做出相應的算法選擇。為了演示我們的方法,我們使用網絡拓撲信息來優化 NCCL 創建的環和樹,以盡可能減少交叉 DC 連接的數量并提高性能。
在我們開發 AI 通信的未來時,我們迫切希望收集反饋,了解您如何使用 NCCL 進行跨 DC 通信、其性能以及我們方法中的任何缺點。請在開發者論壇上與我們聯系,或在 Github 上分享您的反饋。
?