【分布式】小白看Ring算法 - 03

相關系列

【分布式】NCCL部署與測試 - 01
【分布式】入門級NCCL多機并行實踐 - 02
【分布式】小白看Ring算法 - 03
【分布式】大模型分布式訓練入門與實踐 - 04

概述

NCCL(NVIDIA Collective Communications Library)是由NVIDIA開發的一種用于多GPU間通信的庫。NCCL的RING算法是NCCL庫中的一種通信算法,用于在多個GPU之間進行環形通信。

RING算法的基本思想是將多個GPU連接成一個環形結構,每個GPU與相鄰的兩個GPU進行通信。數據沿著環形結構傳遞,直到到達發送方的位置。這樣的環形結構可以有效地利用GPU之間的帶寬,提高通信的效率。

RING算法的步驟如下:

數據拷貝
數據沿著環形路徑傳遞
傳輸完成
進行下一輪通信/結束通信過程
初始化
通信緩沖區
等待
接收方

Scatter-Reduce

以Scatter-Reduce為例,假設有4張GPU,RANK_NUM=4。
則需要根據RANK_NUM把每張CPU劃分為4個chunk。
為什么要這么劃分?

在 NCCL 中,劃分 chunk 的數量與 GPU 的數量相關聯,這是因為 chunk 的目的是將大的消息劃分為多個小的數據塊,以便并行處理和降低通信的延遲。這種劃分通常會基于 GPU 的數量,以確保每個 GPU 可以處理到一部分數據塊,從而提高整體的通信效率。

  1. 并行性: 劃分 chunk 可以增加通信的并行性。每個 GPU 處理自己的數據塊,不同的 GPU 可以并行地執行通信操作,從而提高整體的吞吐量。
  2. 減少延遲: 較小的數據塊通常可以更快地傳輸,因此通過劃分 chunk,可以減少每個通信操作的延遲。這對于一些對通信延遲敏感的應用程序是至關重要的。
  3. 資源分配: NCCL 可能會根據 GPU 的數量來分配適當的資源,例如內存等。通過劃分 chunk,可以更好地管理這些資源。
  4. Load Balancing: 均衡負載是分布式系統中的一個關鍵問題。通過根據 GPU 的數量劃分 chunk,可以更容易地實現負載均衡,確保每個 GPU 處理的工作量相對均勻。

劃分了chunk以后,我們一次RING的通路將會走通4塊GPU,每次只傳輸一塊chunk的數據。這樣需要走很多次通路才能把所有數據傳輸完。
假如 ringIx=0,第一次循環到第三次循環時:
在這里插入圖片描述

我們將綠色視為這次循環需要傳輸的數據。
數據ABCD在不同的GPU中流通。
最終達到以下情況,scatter-reduce就完成了:
在這里插入圖片描述
將圖中藍色部分輸出,就完成了一次ring算法下的Scatter-Reduce。

當然,如果要做All-Reduce,此時不需要繼續按照原來的規則計算類,理論上只需要再算一次All-Gather,就能把藍色的塊分發給其他幾塊卡。All-Reduce的相關講解網絡上很多。此處就不講了。

NCCL代碼流程

1
1
1
1
2
2
2
2
4
4
4
4
5
5
5
5
6
6
6
6
7
7
7
7
8
8
8
8
9
9
9
9
10
10
10
10
11
11
11
11
12
12
12
12
13
13
13
13
rank0:fillInfo
bootstrap AllGather
rank1:fillInfo
rank2:fillInfo
rank3:fillInfo
rank0:getSystem
rank1:getSystem
rank2:getSystem
rank3:getSystem
rank0:computePath
rank1:computePath
rank2:computePath
rank3:computePath
rank0:search channel
rank1:search channel
rank2:search channel
rank3:search channel
bootstrap AllGather
rank0:connect
rank1:connect
rank2:connect
rank3:connect
rank0:setupChannel
rank1:setupChannel
rank2:setupChannel
rank3:setupChannel
rank0:p2pSetup
rank1:p2pSetup
rank2:p2pSetup
rank3:p2pSetup
rank0:tuneModel
rank1:tuneModel
rank2:tuneModel
rank3:tuneModel
rank0:p2pChannel
rank1:p2pChannel
rank2:p2pChannel
rank3:p2pChannel
bootstrap IntraNodeBarrier
rank0:NetProxy
rank1:NetProxy
rank2:NetProxy
rank3:NetProxy

fillInfo:
這段代碼在init.cc中

static ncclResult_t fillInfo(struct ncclComm* comm, struct ncclPeerInfo* info, uint64_t commHash) {info->rank = comm->rank;CUDACHECK(cudaGetDevice(&info->cudaDev));info->hostHash=getHostHash()+commHash;info->pidHash=getPidHash()+commHash;// Get the device MAJOR:MINOR of /dev/shm so we can use that// information to decide whether we can use SHM for inter-process// communication in a container environmentstruct stat statbuf;SYSCHECK(stat("/dev/shm", &statbuf), "stat");info->shmDev = statbuf.st_dev;info->busId = comm->busId;NCCLCHECK(ncclGpuGdrSupport(&info->gdrSupport));return ncclSuccess;
}

這段代碼的目的是為了獲取和存儲與通信相關的信息,以便在NCCL通信中使用。其中包括設備標識、主機哈希、進程ID哈希、共享內存設備標識、總線ID以及對GDR的支持情況等。

在initTransportsRank中,搜索完信息并作第一次AllGather, 收集所有通信節點的信息。
然后再為通信組分配額外的內存,以存儲每個通信節點的信息(包括一個額外的用于表示CollNet root的位置)。
遍歷節點和復制信息時,需要檢查是否存在相同主機哈希和總線ID的重復GPU。如果是,發出警告并返回ncclInvalidUsage錯誤。

后面的一系列過程就是計算路徑,然后這里涉及一些搜索算法,通常會將BFS搜索到的路徑都存在一個位置,選擇更優的路徑。
搜索時也會根據實際情況判斷選擇ring算法或者tree算法。
搜索內容可能是無窮的,因此NCCL設置了一個超時時間,超過該時間則終端搜索。
完成路徑的計算后,再做一次AllGather。

來到scatter-reduce的實現部分:

		size_t realChunkSize;if (Proto::Id == NCCL_PROTO_SIMPLE) {realChunkSize = min(chunkSize, divUp(size-gridOffset, nChannels));realChunkSize = roundUp(realChunkSize, (nthreads-WARP_SIZE)*sizeof(uint64_t)/sizeof(T));}else if (Proto::Id == NCCL_PROTO_LL)realChunkSize = size-gridOffset < loopSize ? args->coll.lastChunkSize : chunkSize;else if (Proto::Id == NCCL_PROTO_LL128)realChunkSize = min(divUp(size-gridOffset, nChannels*minChunkSizeLL128)*minChunkSizeLL128, chunkSize);realChunkSize = int(realChunkSize);ssize_t chunkOffset = gridOffset + bid*int(realChunkSize);

這里涉及了NCCL協議的通信模式:
一共有三種,分別是NCCL_PROTO_SIMPLE、NCCL_PROTO_LL和NCCL_PROTO_LL128。

NCCL_PROTO_SIMPLE:

描述: 使用簡單的通信協議。
差異點: 計算realChunkSize時,采用了一些特殊的邏輯,其中min(chunkSize, divUp(size-gridOffset, nChannels))用于確定實際的塊大小,并通過roundUp調整為合適的大小。這可能涉及到性能和資源的考慮,以及對通信模式的調整。

NCCL_PROTO_LL:

描述: 使用連續鏈表(Linked List,LL)的通信協議。
差異點: 在計算realChunkSize時,首先檢查size-gridOffset < loopSize條件,如果為真,則使用args->coll.lastChunkSize,否則使用默認的chunkSize。這可能與LL協議的特性有關,具體考慮了循環的情況。
NCCL_PROTO_LL128:

描述: 使用連續鏈表的通信協議,每次傳輸128字節。
差異點: 計算realChunkSize時,采用了min(divUp(size-gridOffset, nChannels*minChunkSizeLL128)*minChunkSizeLL128, chunkSize)的邏輯。這考慮了128字節的限制,以及對通信塊大小的一些限制。
總體來說,這三種協議模式的區別主要體現在計算realChunkSize的邏輯上,這可能受到性能、資源利用、通信模式等方面的不同考慮。具體選擇哪種協議模式通常取決于系統的特性和應用場景的需求。

Protocol ModeDescriptionCalculation of realChunkSize
NCCL_PROTO_SIMPLEUses a simple communication protocol.realChunkSize = roundUp(min(chunkSize, divUp(size-gridOffset, nChannels)), (nthreads-WARP_SIZE)*sizeof(uint64_t)/sizeof(T))
NCCL_PROTO_LLUses a linked list (LL) communication protocol.realChunkSize = size-gridOffset < loopSize ? args->coll.lastChunkSize : chunkSize
NCCL_PROTO_LL128Uses a linked list (LL) communication protocol, with each transfer involving 128 bytes.realChunkSize = min(divUp(size-gridOffset, nChannels*minChunkSizeLL128)*minChunkSizeLL128, chunkSize)

最后是正式計算部分:

 /////////////// begin ReduceScatter steps ///////////////ssize_t offset;int nelem = min(realChunkSize, size-chunkOffset);int rankDest;// step 0: push data to next GPUrankDest = ringRanks[nranks-1];offset = chunkOffset + rankDest * size;prims.send(offset, nelem);// k-2 steps: reduce and copy to next GPUfor (int j=2; j<nranks; ++j) {rankDest = ringRanks[nranks-j];offset = chunkOffset + rankDest * size;prims.recvReduceSend(offset, nelem);}// step k-1: reduce this buffer and data, which will produce the final resultrankDest = ringRanks[0];offset = chunkOffset + rankDest * size;prims.recvReduceCopy(offset, chunkOffset, nelem, /*postOp=*/true);

ssize_t offset; int nelem = min(realChunkSize, size-chunkOffset); int rankDest;:

offset 是一個偏移量變量,用于指定數據在通信緩沖區中的位置。
nelem 表示每次操作的元素個數,取 realChunkSize 和 size-chunkOffset 的較小值。
rankDest 是目標GPU的排名。

第一步:將數據推送到下一個GPU。
計算目標GPU的排名 rankDest 和在通信緩沖區中的偏移量 offset。
調用 prims.send 函數,將數據從當前GPU發送到目標GPU。
// k-2 steps: reduce and copy to next GPU:

第2到第k-1步:
將數據在環形路徑上經過各個GPU節點,依次進行Reduce操作,并將結果復制到下一個GPU。
通過循環,依次計算目標GPU的排名 rankDest 和在通信緩沖區中的偏移量 offset。
調用 prims.recvReduceSend 函數,接收數據并執行Reduce操作,然后將結果發送到下一個GPU。

第k-1步:
將最后一個GPU的數據進行Reduce操作,得到最終的結果。
計算目標GPU的排名 rankDest 和在通信緩沖區中的偏移量 offset。
調用 prims.recvReduceCopy 函數,接收數據并執行Reduce操作,然后將結果復制到指定的位置,最終產生最終的ReduceScatter結果。

在實際運行中,我們在host端的代碼只是規定計算流,當這些定義好的原子操作加入到stream中去以后,就由固定的流來分配實際運行的情況了。

加入Barria,在本地(intra-node)執行一個屏障操作,確保同一節點內的所有GPU都達到了同步點。

 // Compute time models for algorithm and protocol combinationsNCCLCHECK(ncclTopoTuneModel(comm, minCompCap, maxCompCap, &treeGraph, &ringGraph, &collNetGraph));// Compute nChannels per peer for p2pNCCLCHECK(ncclTopoComputeP2pChannels(comm));if (ncclParamNvbPreconnect()) {// Connect p2p when using NVB pathint nvbNpeers;int* nvbPeers;NCCLCHECK(ncclTopoGetNvbGpus(comm->topo, comm->rank, &nvbNpeers, &nvbPeers));for (int r=0; r<nvbNpeers; r++) {int peer = nvbPeers[r];int delta = (comm->nRanks + (comm->rank-peer)) % comm->nRanks;for (int c=0; c<comm->p2pnChannelsPerPeer; c++) {int channelId = (delta+comm->p2pChannels[c]) % comm->p2pnChannels;if (comm->channels[channelId].peers[peer].recv[0].connected == 0) { // P2P uses only 1 connectorcomm->connectRecv[peer] |= (1<<channelId);}}delta = (comm->nRanks - (comm->rank-peer)) % comm->nRanks;for (int c=0; c<comm->p2pnChannelsPerPeer; c++) {int channelId = (delta+comm->p2pChannels[c]) % comm->p2pnChannels;if (comm->channels[channelId].peers[peer].send[0].connected == 0) { // P2P uses only 1 connectorcomm->connectSend[peer] |= (1<<channelId);}}}NCCLCHECK(ncclTransportP2pSetup(comm, NULL, 0));free(nvbPeers);}NCCLCHECK(ncclCommSetIntraProc(comm, intraProcRank, intraProcRanks, intraProcRank0Comm));/* Local intra-node barrier */NCCLCHECK(bootstrapBarrier(comm->bootstrap, comm->intraNodeGlobalRanks, intraNodeRank, intraNodeRanks, (int)intraNodeRank0pidHash));if (comm->nNodes) NCCLCHECK(ncclProxyCreate(comm));

以上就是整個scatter-reduce的流程。

相關系列

【分布式】NCCL部署與測試 - 01
【分布式】入門級NCCL多機并行實踐 - 02
【分布式】小白看Ring算法 - 03
【分布式】大模型分布式訓練入門與實踐 - 04

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/165141.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/165141.shtml
英文地址,請注明出處:http://en.pswp.cn/news/165141.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

通過 python 腳本遷移 Redis 數據

背景 需求&#xff1a;需要將的 Redis 數據遷移由云廠商 A 遷移至云廠商 B問題&#xff1a;云版本的 Redis 版本不支持 SYNC、MIGRATE、BGSAVE 等命令&#xff0c;使得許多工具用不了&#xff08;如 redis-port&#xff09; 思路 &#xff08;1&#xff09;從 Redis A 獲取所…

GoLand 2023.2.5(GO語言集成開發工具環境)

GoLand是一款專門為Go語言開發者打造的集成開發環境&#xff08;IDE&#xff09;。它能夠提供一系列功能&#xff0c;如代碼自動完成、語法高亮、代碼格式化、代碼重構、代碼調試等等&#xff0c;使編寫代碼更加高效和舒適。 GoLand的特點包括&#xff1a; 1. 智能代碼補全&a…

json 去除特殊字符換行等符號

由于字符串中有出現了 換行符&#xff0c;導致轉json失敗&#xff0c;報錯&#xff1a;json parse error。 一般來講&#xff0c;直接用string的replace方法就可以了 String str "{\"adrdet\":\"阿歌嘎\n嘎、\",\"date\":\"2023/06/…

Ubuntu安裝CUDA驅動

Ubuntu安裝CUDA驅動 前言官網安裝確認安裝版本安裝CUDA Toolkit 前言 CUDA驅動一般指CUDA Toolkit&#xff0c;可通過Nvidia官網下載安裝。本文介紹安裝方法。 官網 CUDA Toolkit 最新版&#xff1a;CUDA Toolkit Downloads | NVIDIA Developer CUDA Toolkit 最新版文檔&…

NX二次開發UF_CAM_update_list_object_customization 函數介紹

文章作者&#xff1a;里海 來源網站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_CAM_update_list_object_customization Defined in: uf_cam.h int UF_CAM_update_list_object_customization(tag_t * object_tags ) overview 概述 This function provids the…

UDP客戶端使用connect與UDP服務器使用send函數和recv函數收發數據

服務器代碼編譯運行 服務器udpconnectToServer.c的代碼如下&#xff1a; #include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<arpa/inet.h> #include<sys/socket.h> #include<errno.h> #inclu…

Okhttp 淺析

安全的連接 OkHttpClient: OkHttpClient: 1.線程調度 2.連接池,有則復用,沒有就創建 3.interceptor 4.interceptor 5.監聽工廠 6.是否失敗重試 7.自動修正訪問,如果沒有權限或認證 8是否重定向 followRedirects 9.協議切換時候是否繼續重定向 10.Cookie jar 容器 默認…

Python 的 socket 模塊套接字編程(簡單入門級別)

Python 的 socket 模塊提供了對套接字編程的支持&#xff0c;允許你在網絡上進行數據傳輸。套接字是一個抽象的概念&#xff0c;它允許程序在網絡中的不同節點之間進行通信。 下面是 socket 模塊中一些常用的函數和類&#xff1a; 1. 創建套接字&#xff1a; socket.socket(…

pycharm 創建的django目錄和命令行創建的django再使用pycharm打開的目錄對比截圖 及相關

pytcharm創建django的項目 命令行創建的django 命令行創建項目時 不帶路徑時 (.venv) D:\gbCode>django-admin startproject gbCode 命令行創建項目時 帶路徑時 -- 所以如果有目錄就指定路徑好 (.venv) D:\gbCode>django-admin startproject gbCode d:\gbCode\

洛谷P1219 [USACO1.5] 八皇后【n皇后問題】【深搜+回溯 經典題】【附O(1)方法】

P1219 [USACO1.5] 八皇后 Checker Challenge 前言題目題目描述輸入格式輸出格式樣例 #1樣例輸入 #1樣例輸出 #1 提示題目分析注意事項 代碼深搜回溯打表 后話額外測試用例樣例輸入 #2樣例輸出 #2 王婆賣瓜 題目來源 前言 也是說到做到&#xff0c;來做搜索的題&#xff08;雖…

微機原理_2

一、單項選擇題(本大題共15小題,每小題3分,共45分。在每小題給出的四個備選項中,選出一個正確的答案&#xff0c;請將選定的答案填涂在答題紙的相應位置上。&#xff09; 下列數中最大的數為&#xff08;&#xff09; A. 10010101B B. (126)8 C. 96H D. 100 CPU 執行 OUT 60H,…

Android 9.0 隱藏設置顯示中自動調節亮度

Android 9.0 隱藏設置顯示中自動調節亮度 最近收到郵件需求提到想要隱藏設置顯示中的自動調節亮度&#xff0c;具體修改參照如下&#xff1a; /vendor/mediatek/proprietary/packages/apps/MtkSettings/res/xml/display_settings.xml - <Preference<!--Preferencea…

西門子(Siemens)仿真PLC啟動報錯處理

目錄 一、背景&#xff1a; 二、卸載軟件 三、安裝軟件 三、啟動軟件 四、下載PORTAL項目 五、測試 一、背景&#xff1a; 在啟動S7-PLCSIM Advanced V3.0仿真PLC時報錯&#xff0c;報錯信息為&#xff1a;>>Siemens PLCSIM Virtual Switch<<is misconfigu…

Ubuntu 23.10 服務器版本 ifconfig 查不到網卡 ip(已解決)

文章目錄 1、問題描述2、 解決方案 1、問題描述 服務器&#xff1a;ubuntu 23.10 經常會遇到虛擬機添加僅主機網卡后&#xff0c;通過 ifconfig 無法獲取其網卡 ip 2、 解決方案 修改網卡配置文件&#xff1a; # 進入網卡配置文件目錄 cd /etc/netplan # 備份原始文件 cp …

ArgoWorkflow教程(一)---DevOps 另一選擇?云原生 CICD: ArgoWorkflow 初體驗

來自&#xff1a;探索云原生 https://www.lixueduan.com 原文&#xff1a;https://www.lixueduan.com/posts/devops/argo-workflow/01-deploy-argo-workflows/ 本文主要記錄了如何在 k8s 上快速部署云原生的工作流引擎 ArgoWorkflow。 ArgoWorkflow 是什么 Argo Workflows 是…

網絡安全如何自學?

1.網絡安全是什么 網絡安全可以基于攻擊和防御視角來分類&#xff0c;我們經常聽到的 “紅隊”、“滲透測試” 等就是研究攻擊技術&#xff0c;而“藍隊”、“安全運營”、“安全運維”則研究防御技術。 2.網絡安全市場 一、是市場需求量高&#xff1b; 二、則是發展相對成熟…

使用 Vue3 + Pinia + Ant Design Vue3 搭建后臺管理系統

Vue3 & Ant Design Vue3基礎 nodejs版本要求&#xff1a;node-v18.16.0-x64 nodejs基礎配置 npm -v node -vnpm config set prefix "D:\software\nodejs\node_global" npm config set cache "D:\software\nodejs\node_cache"npm config get registry …

2023亞太賽數學建模A題:采果機器人的圖像識別技術思路模型代碼

亞太A題&#xff1a;采果機器人的圖像識別技術 A題完整思路獲取 &#xff1a;獲取見文末名片&#xff0c;第一時間更新 中國是世界上最大的蘋果生產國&#xff0c;年產量約為3500萬噸。與此同時&#xff0c;中國也是世 界上最大的蘋果出口國&#xff0c;全球每兩個蘋果中就有…

Android設計模式--裝飾模式

千淘萬漉雖辛苦&#xff0c;吹盡黃沙始到金 一&#xff0c;定義 動態地給一個對象添加一些額外的職責。就增加功能來說&#xff0c;裝飾模式相比生成子類更為靈活。 裝飾模式也叫包裝模式&#xff0c;結構型設計模式之一&#xff0c;其使用一種對客戶端透明的方式來動態地擴展…

QT 中的元對象系統

作為一名十幾年的 C 程序員&#xff0c;最近一段時間使用 QT 開發程序&#xff0c;發現 QT 中還是有許多值得深入理解的技術。QT 不僅僅是一個應用程序開發框架&#xff0c;還有一些對標準 C 的擴充。本文和大家一起探討 QT 中的元對象系統。 在分析 QT 中的元對象系統之前&…