隨著我們從單個(gè) GPU 轉(zhuǎn)移到多個(gè) GPU,再轉(zhuǎn)移到包含多個(gè) GPU 的多臺(tái)服務(wù)器,可能都分布在多個(gè)機(jī)架和網(wǎng)絡(luò)交換機(jī)上,我們的分布式和并行訓(xùn)練算法需要變得更加復(fù)雜。細(xì)節(jié)很重要,因?yàn)椴煌幕ミB具有非常不同的帶寬(例如,NVLink 可以在適當(dāng)?shù)脑O(shè)置下跨 6 個(gè)鏈路提供高達(dá) 100 GB/s 的速度,PCIe 4.0(16 通道)提供 32 GB/s,而即使是高速 100GbE 以太網(wǎng)也只能達(dá)到到 10 GB/秒)。同時(shí),期望統(tǒng)計(jì)建模師成為網(wǎng)絡(luò)和系統(tǒng)方面的專家是不合理的。
Smola 和 Narayanamurthy ( 2010 )在分布式潛變量模型的背景下引入了參數(shù)服務(wù)器的核心思想 。隨后在Ahmed等人中描述了推拉語義。( 2012 )以及Li等人對(duì)系統(tǒng)和開源庫(kù)的描述 。(2014 年)。在下文中,我們將激勵(lì)效率所需的組件。
13.7.1。數(shù)據(jù)并行訓(xùn)練
讓我們回顧一下分布式訓(xùn)練的數(shù)據(jù)并行訓(xùn)練方法。我們將使用它來排除本節(jié)中的所有其他內(nèi)容,因?yàn)樗趯?shí)踐中實(shí)施起來要簡(jiǎn)單得多。由于現(xiàn)在 GPU 有足夠的內(nèi)存,因此幾乎沒有任何用例(除了圖上的深度學(xué)習(xí))首選任何其他并行策略。圖 13.7.1描述了我們?cè)?3.5 節(jié)中實(shí)現(xiàn)的數(shù)據(jù)并行的變體 。其中的關(guān)鍵方面是在將更新的參數(shù)重新廣播到所有 GPU 之前,梯度的聚合發(fā)生在一個(gè) GPU (GPU 0) 上。
圖 13.7.1左:?jiǎn)?GPU 訓(xùn)練。右圖:多 GPU 訓(xùn)練的一種變體:(1) 我們計(jì)算損失和梯度,(2) 所有梯度都聚集在一個(gè) GPU 上,(3) 發(fā)生參數(shù)更新并將參數(shù)重新分配給所有 GPU。
回想起來,在 GPU 0 上聚合的決定似乎是臨時(shí)的。畢竟,我們還不如聚合在 CPU 上。事實(shí)上,我們甚至可以決定在一個(gè) GPU 上聚合一些參數(shù),在另一個(gè) GPU 上聚合一些其他參數(shù)。只要優(yōu)化算法支持這一點(diǎn),就沒有我們不能這樣做的真正原因。例如,如果我們有四個(gè)具有相關(guān)梯度的參數(shù)向量 g1,…,g4我們可以在一個(gè) GPU 上聚合梯度gi (i=1,…,4).
這種推理似乎是武斷和輕率的。畢竟,數(shù)學(xué)自始至終都是一樣的。然而,我們正在處理真實(shí)的物理硬件,其中不同的總線具有不同的帶寬,如第 13.4 節(jié)所述 ??紤]一個(gè)真實(shí)的 4 路 GPU 服務(wù)器,如圖13.7.2所示。如果連接特別好,它可能有 100 GbE 網(wǎng)卡。更典型的數(shù)字在 1–10 GbE 范圍內(nèi),有效帶寬為 100 MB/s 至 1 GB/s。由于 CPU 的 PCIe 通道太少而無法直接連接到所有 GPU(例如,消費(fèi)級(jí) Intel CPU 有 24 條通道),我們需要一個(gè) 多路復(fù)用器。CPU 在 16x Gen3 鏈路上的帶寬為 16 GB/s。這也是每個(gè)人的速度GPU 連接到交換機(jī)。這意味著設(shè)備之間的通信更加有效。
圖 13.7.2一個(gè) 4 路 GPU 服務(wù)器。
為了論證,我們假設(shè)梯度為 160 MB。在這種情況下,將梯度從所有剩余的 3 個(gè) GPU 發(fā)送到第四個(gè) GPU 需要 30 毫秒(每次傳輸需要 10 毫秒 = 160 MB / 16 GB/s)。再加上 30 毫秒來傳回權(quán)重向量,我們總共需要 60 毫秒。如果我們將所有數(shù)據(jù)發(fā)送到 CPU,我們會(huì)受到 40 毫秒的懲罰,因?yàn)樗膫€(gè) GPU 中的每一個(gè)都需要將數(shù)據(jù)發(fā)送到 CPU,總共需要 80 毫秒。最后假設(shè)我們能夠?qū)⑻荻确殖?4 個(gè)部分,每個(gè)部分 40 MB?,F(xiàn)在我們可以同時(shí)在不同的 GPU 上聚合每個(gè)部分因?yàn)?PCIe 交換機(jī)在所有鏈路之間提供全帶寬操作。這需要 7.5 毫秒而不是 30 毫秒,同步操作總共需要 15 毫秒。簡(jiǎn)而言之,根據(jù)我們同步參數(shù)的方式,同一操作可能需要 15 毫秒到 80 毫秒不等。 圖 13.7.3描述了交換參數(shù)的不同策略。
圖 13.7.3參數(shù)同步策略。
請(qǐng)注意,在提高性能方面,我們還有另一種工具可供使用:在深度網(wǎng)絡(luò)中,需要一些時(shí)間來計(jì)算從頂部到底部的所有梯度。即使我們?nèi)栽诿τ跒槠渌麉?shù)組計(jì)算梯度,我們也可以開始同步某些參數(shù)組的梯度。 有關(guān)如何在 Horovod中執(zhí)行此操作的詳細(xì)信息,請(qǐng)參見例如Sergeev 和 Del Balso ( 2018 )。
13.7.2。環(huán)同步
當(dāng)談到現(xiàn)代深度學(xué)習(xí)硬件上的同步時(shí),我們經(jīng)常會(huì)遇到大量定制的網(wǎng)絡(luò)連接。例如,AWS p3.16xlarge 和 NVIDIA DGX-2 實(shí)例共享圖 13.7.4的連接結(jié)構(gòu)。每個(gè) GPU 通過 PCIe 鏈路連接到主機(jī) CPU,該鏈路最高運(yùn)行速度為 16 GB/s。此外,每個(gè) GPU 還有 6 個(gè) NVLink 連接,每個(gè)連接都能夠雙向傳輸 300 Gbit/s。這相當(dāng)于每個(gè)鏈接每個(gè)方向大約 18 GB/s。簡(jiǎn)而言之,總 NVLink 帶寬明顯高于 PCIe 帶寬。問題是如何最有效地使用它。
圖 13.7.4 8 個(gè) V100 GPU 服務(wù)器上的 NVLink 連接(圖片由 NVIDIA 提供)。
事實(shí)證明,最佳同步策略是將網(wǎng)絡(luò)分解為兩個(gè)環(huán),并使用它們直接同步數(shù)據(jù) (Wang et al. , 2018)。圖 13.7.5 說明網(wǎng)絡(luò)可以分解為具有雙 NVLink 帶寬的一個(gè)環(huán) (1-2-3-4-5-6-7-8-1) 和一個(gè) (1-4-6-3- 5-8-2-7-1) 具有常規(guī)帶寬。在這種情況下設(shè)計(jì)高效的同步協(xié)議并非易事。
圖 13.7.5將 NVLink 網(wǎng)絡(luò)分解為兩個(gè)環(huán)。
考慮以下思想實(shí)驗(yàn):給定一環(huán)n 計(jì)算節(jié)點(diǎn)(或 GPU),我們可以將梯度從第一個(gè)節(jié)點(diǎn)發(fā)送到第二個(gè)節(jié)點(diǎn)。在那里它被添加到局部梯度并發(fā)送到第三個(gè)節(jié)點(diǎn),依此類推。后n?1步驟聚合梯度可以在最后訪問的節(jié)點(diǎn)中找到。也就是說,聚合梯度的時(shí)間隨著節(jié)點(diǎn)的數(shù)量線性增長(zhǎng)。但如果我們這樣做,算法效率會(huì)很低。畢竟,任何時(shí)候都只有一個(gè)節(jié)點(diǎn)在通信。如果我們把梯度分解成 n塊并開始同步塊i從節(jié)點(diǎn)開始i?由于每個(gè)塊的大小1/n現(xiàn)在的總時(shí)間(n?1)/n≈1. 換句話說,隨著我們?cè)黾迎h(huán)的大小,聚合梯度所花費(fèi)的時(shí)間不會(huì)增加。這是一個(gè)相當(dāng)驚人的結(jié)果。圖 13.7.6 說明了步驟的順序n=4節(jié)點(diǎn)。
圖 13.7.6跨 4 個(gè)節(jié)點(diǎn)的環(huán)同步。每個(gè)節(jié)點(diǎn)開始將部分梯度傳輸?shù)狡渥筻従?,直到可以在其右鄰居中找到組裝的梯度。
如果我們使用跨 8 個(gè) V100 GPU 同步 160 MB 的相同示例,我們將得到大約 2?160MB/(3?18GB/s)≈6ms. 這比使用 PCIe 總線要好,即使我們現(xiàn)在使用 8 個(gè) GPU。請(qǐng)注意,在實(shí)踐中,這些數(shù)字會(huì)更糟一些,因?yàn)樯疃葘W(xué)習(xí)框架通常無法將通信組合成大量突發(fā)傳輸。
請(qǐng)注意,有一個(gè)常見的誤解,認(rèn)為環(huán)同步與其他同步算法根本不同。唯一的區(qū)別是與簡(jiǎn)單的樹相比,同步路徑稍微復(fù)雜一些。
13.7.3。多機(jī)訓(xùn)練
在多臺(tái)機(jī)器上進(jìn)行分布式訓(xùn)練增加了一個(gè)進(jìn)一步的挑戰(zhàn):我們需要與僅通過相對(duì)較低帶寬的結(jié)構(gòu)連接的服務(wù)器進(jìn)行通信,在某些情況下,這種結(jié)構(gòu)的速度可能會(huì)慢一個(gè)數(shù)量級(jí)以上??缭O(shè)備同步很棘手。畢竟,不同機(jī)器運(yùn)行訓(xùn)練代碼的速度會(huì)有細(xì)微差別。因此,如果我們想使用同步分布式優(yōu)化, 我們需要同步它們。圖 13.7.7說明了分布式并行訓(xùn)練是如何發(fā)生的。
在每臺(tái)機(jī)器上讀?。ú煌模┮慌鷶?shù)據(jù),將其拆分到多個(gè) GPU 并傳輸?shù)?GPU 內(nèi)存。預(yù)測(cè)和梯度分別在每個(gè) GPU 批次上計(jì)算。
來自所有本地 GPU 的梯度聚合在一個(gè) GPU 上(或其中的一部分聚合在不同的 GPU 上)。
梯度被發(fā)送到 CPU。
CPU 將梯度發(fā)送到聚合所有梯度的中央?yún)?shù)服務(wù)器。
然后使用聚合梯度來更新參數(shù),并將更新后的參數(shù)廣播回各個(gè) CPU。
信息被發(fā)送到一個(gè)(或多個(gè))GPU。
更新后的參數(shù)分布在所有 GPU 上。
圖13.7.7多機(jī)多GPU分布式并行訓(xùn)練。
這些操作中的每一個(gè)看起來都相當(dāng)簡(jiǎn)單。而且,事實(shí)上,它們可以在一臺(tái)機(jī)器上高效地執(zhí)行。但是,一旦我們查看多臺(tái)機(jī)器,我們就會(huì)發(fā)現(xiàn)中央?yún)?shù)服務(wù)器成為瓶頸。畢竟每臺(tái)服務(wù)器的帶寬是有限的,因此對(duì)于m工作人員將所有梯度發(fā)送到服務(wù)器所需的時(shí)間是O(m). 我們可以通過增加服務(wù)器數(shù)量來突破這個(gè)障礙n. 此時(shí)每臺(tái)服務(wù)器只需要存儲(chǔ)O(1/n)的參數(shù),因此更新和優(yōu)化的總時(shí)間變?yōu)?O(m/n). 無論我們正在處理多少工人,匹配這兩個(gè)數(shù)字都會(huì)產(chǎn)生恒定的縮放比例。在實(shí)踐中,我們使用同一臺(tái)機(jī)器作為工作人員和服務(wù)器。 圖 13.7.8說明了該設(shè)計(jì)(詳見 ( Li et al. , 2014 ))。特別是,確保多臺(tái)機(jī)器在沒有不合理延遲的情況下工作是非常重要的。
圖 13.7.8頂部:?jiǎn)蝹€(gè)參數(shù)服務(wù)器是一個(gè)瓶頸,因?yàn)樗膸捠怯邢薜?。底部:多個(gè)參數(shù)服務(wù)器存儲(chǔ)部分具有聚合帶寬的參數(shù)。
13.7.4。鍵值存儲(chǔ)
在實(shí)踐中實(shí)施分布式多 GPU 訓(xùn)練所需的步驟并非易事。這就是為什么使用通用抽象是值得的,即具有重新定義的更新語義的鍵值存儲(chǔ)。
跨越許多工作人員和許多 GPU 的梯度計(jì)算i 可以定義為
(13.7.1)gi=∑k∈workers∑j∈GPUsgijk,
在哪里gijk是漸變的一部分i在 GPU 上拆分j工人的k. 此操作的關(guān)鍵方面是它是可交換歸約,也就是說,它將多個(gè)向量變成一個(gè)向量,并且應(yīng)用操作的順序無關(guān)緊要。這對(duì)我們的目的非常有用,因?yàn)槲覀儾恍枰ㄐ枰?duì)何時(shí)接收哪個(gè)梯度進(jìn)行細(xì)粒度控制。此外,請(qǐng)注意,此操作在不同的i.
這使我們能夠定義以下兩個(gè)操作:push和 pull,累積梯度,pull檢索聚合梯度。由于我們有很多不同的梯度集(畢竟我們有很多層),我們需要用一個(gè)鍵來索引梯度i. 這種與鍵值存儲(chǔ)的相似性,例如 Dynamo 中引入的鍵值存儲(chǔ) (DeCandia等人,2007 年)并非巧合。它們也滿足許多相似的特征,尤其是在涉及跨多個(gè)服務(wù)器分布參數(shù)時(shí)。
鍵值存儲(chǔ)的推拉操作描述如下:
push(key, value)將特定梯度(值)從工作人員發(fā)送到公共存儲(chǔ)。在那里該值被聚合,例如,通過將其相加。
pull(key, value)從公共存儲(chǔ)中檢索聚合值,例如,在組合所有 worker 的梯度之后。
通過將有關(guān)同步的所有復(fù)雜性隱藏在簡(jiǎn)單的推拉操作背后,我們可以將希望能夠用簡(jiǎn)單術(shù)語表達(dá)優(yōu)化的統(tǒng)計(jì)建模人員和需要處理分布式同步固有復(fù)雜性的系統(tǒng)工程師的關(guān)注分離開來。
13.7.5。概括
同步需要高度適應(yīng)服務(wù)器內(nèi)的特定網(wǎng)絡(luò)基礎(chǔ)設(shè)施和連接。這會(huì)對(duì)同步所需的時(shí)間產(chǎn)生重大影響。
環(huán)同步對(duì)于 p3 和 DGX-2 服務(wù)器可能是最佳的。對(duì)于其他人可能不是那么多。
當(dāng)添加多個(gè)參數(shù)服務(wù)器以增加帶寬時(shí),分層同步策略效果很好。
13.7.6。練習(xí)
你能進(jìn)一步增加環(huán)同步嗎?提示:您可以雙向發(fā)送消息。
是否可以允許異步通信(同時(shí)計(jì)算仍在進(jìn)行中)?它如何影響性能?
如果我們?cè)陂L(zhǎng)時(shí)間運(yùn)行的計(jì)算過程中丟失了一臺(tái)服務(wù)器怎么辦?我們?nèi)绾卧O(shè)計(jì)容錯(cuò)機(jī)制來避免完全重新啟動(dòng)計(jì)算?
Discussions
-
服務(wù)器
+關(guān)注
關(guān)注
12文章
8963瀏覽量
85087 -
pytorch
+關(guān)注
關(guān)注
2文章
802瀏覽量
13115
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論