溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

基于AllReduce的彈性分布式使用方法是什么

發(fā)布時間:2022-01-11 17:46:33 來源:億速云 閱讀:127 作者:iii 欄目:云計算

今天小編給大家分享一下基于AllReduce的彈性分布式使用方法是什么的相關(guān)知識點,內(nèi)容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

背景

首先我們簡要回顧一下深度學習的模型訓(xùn)練。這里所說的訓(xùn)練,指的是利用數(shù)據(jù)通過計算梯度下降的方式迭代地去優(yōu)化神經(jīng)網(wǎng)絡(luò)的參數(shù),最終輸出網(wǎng)絡(luò)模型的過程。在這個過程中,通常在迭代計算的環(huán)節(jié),會借助 GPU 進行計算的加速。相比于 CPU 而言,可以達到 10-100 倍的加速效果。而分布式的模型訓(xùn)練,最早是由 Mu Li 在 OSDI'14 上提出的。在傳統(tǒng)的模型訓(xùn)練中,迭代計算的過程只能利用當前進程所在主機上的所有硬件資源。但是單機的擴展性始終是有限的,在數(shù)據(jù)集規(guī)模特別大或者模型特別復(fù)雜的時候,單機訓(xùn)練的速度就會有些捉襟見肘。分布式的訓(xùn)練可以借助不同主機上的硬件資源進行訓(xùn)練加速,大大提高訓(xùn)練速度。

Horovod 是一款基于 AllReduce 的分布式訓(xùn)練框架。憑借其對 TensorFlow、PyTorch 等主流深度學習框架的支持,以及通信優(yōu)化等特點,Horovod 被廣泛應(yīng)用于數(shù)據(jù)并行的訓(xùn)練中。在 Horovod 中,訓(xùn)練進程是平等的參與者,每個進程既負責梯度的分發(fā),也負責具體的梯度計算。如下圖所示,三個 Worker 中的梯度被均衡地劃分為三份,通過 4 次通信,能夠完成集群梯度的計算和同步。

基于AllReduce的彈性分布式使用方法是什么

依托 AllReduce 的分布式訓(xùn)練由于其簡單易懂的編程邏輯和大幅提升的訓(xùn)練速度,逐漸成為分布式訓(xùn)練的主流方式。然而,當前這種模式依然存在一些問題:

  • 首先,AI 訓(xùn)練的成本問題顯著。借助于 Kubernetes,大規(guī)模分布式訓(xùn)練雖然已經(jīng)不再復(fù)雜,但是高昂的訓(xùn)練成本使得這項技術(shù)難以真正做到普惠。

  • 其次,相比于單機的訓(xùn)練,分布式訓(xùn)練有更大的可能出現(xiàn)任務(wù)失敗的情況。在分布式訓(xùn)練中,有多個進程同時參與訓(xùn)練,而其中的某個進程出現(xiàn)了問題,整個訓(xùn)練任務(wù)都會因此而失敗。尤其是當訓(xùn)練任務(wù)需要持續(xù)幾天甚至幾個禮拜時,這個問題就會顯得尤為嚴重。

  • 同時,由于一些混部的集群存在業(yè)務(wù)壓力周期性波動的特性,在閑時 GPU 占用率通常不到 40%。但是與之相對的是,在任務(wù)密集提交時,集群的資源又會出現(xiàn)緊張的情況。資源利用在時間上的不均衡問題非常突出。

彈性訓(xùn)練

為了解決上述問題,更好地向分布式訓(xùn)練釋放云原生的紅利,業(yè)界提出了彈性訓(xùn)練這一概念。

在傳統(tǒng)的深度學習分布式訓(xùn)練任務(wù)中,通常任務(wù)的實例配置是固定的。這很大程度上限制了任務(wù)的靈活性和訓(xùn)練速度,對于整個集群的資源利用率而言也不友好。而彈性訓(xùn)練,就是指讓訓(xùn)練任務(wù)能夠在運行時動態(tài)地調(diào)整參與計算的實例數(shù)量。這使得訓(xùn)練更加靈活,同時可以配合集群的負載進行更好的擴縮容和調(diào)度。這一特性為訓(xùn)練場景帶來了諸多收益:

  • 容錯性的提升。在這樣的選型下,所有實例的失敗都是可以容忍的。任務(wù)不再會因為某個進程出錯而導(dǎo)致任務(wù)整體的失敗。

  • 資源利用率的提升。在集群資源緊張時,通過減少低優(yōu)先級訓(xùn)練任務(wù)的實例數(shù)量,能夠保證高優(yōu)先級訓(xùn)練任務(wù)的資源配額,保證業(yè)務(wù)的 SLA。在集群資源閑置時,又可以通過創(chuàng)建更多實例加入訓(xùn)練的方式,將原本閑置的 GPU 等資源利用起來,加速訓(xùn)練。這不僅使得任務(wù)的訓(xùn)練速度得到了提升,同時也提高了集群的資源利用率。

  • 實現(xiàn)云原生的 AI 訓(xùn)練,配合競價實例等云上資源更好地降低上云成本。競價實例相比于按量付費等實例有著非常大的成本優(yōu)勢,但是也面臨著隨時可能被回收的問題。彈性訓(xùn)練能夠完美地契合這一場景,在競價實例可用時,在競價實例中創(chuàng)建訓(xùn)練任務(wù),在競價實例被回收時,訓(xùn)練任務(wù)仍然能夠繼續(xù)下去。

彈性分布式訓(xùn)練能夠很好地解決分布式訓(xùn)練在成本、資源利用率和容錯等方面的問題。盡管看起來彈性訓(xùn)練只是能夠?qū)⒂?xùn)練任務(wù)的實例動態(tài)調(diào)整,但是它能夠與公有云提供的云原生能力產(chǎn)生相互的作用,產(chǎn)生更大的價值。

在我們實際的測試中,基于 Horovod 的彈性訓(xùn)練在競價實例上,可以將每 GPU 時的花費從 16.21 元降低到了 1.62 元,整個模型訓(xùn)練的成本可以下降接近 70%。而如果在保持花費不變的情況下,競價實例上的彈性模型訓(xùn)練可以購買到更多的 GPU 卡,訓(xùn)練速度能夠提升 5 到 10 倍。原本需要一天的訓(xùn)練任務(wù),可以在幾個小時內(nèi)完成。更進一步地,結(jié)合彈性訓(xùn)練與集群調(diào)度,有更多的可能性可以探索。

Horovod 是目前在數(shù)據(jù)并行的分布式訓(xùn)練中應(yīng)用最多的訓(xùn)練框架之一,因此我們以訓(xùn)練框架 Horovod 為例,介紹 Horovod 的彈性訓(xùn)練方案如何在云原生的環(huán)境下落地。

Horovod Elastic

Uber 開源的 Horovod 框架作為數(shù)據(jù)并行模式下廣泛使用的訓(xùn)練框架,在 2020 年夏天也開始著手解決彈性訓(xùn)練這個需求。最終 Elastic Horovod 在 Horovod v0.20.0 版本發(fā)布中面世。

基于AllReduce的彈性分布式使用方法是什么

為了實現(xiàn)彈性訓(xùn)練的能力,Horovod Elastic 對 Horovod 的架構(gòu)和實現(xiàn)進行了一定的修改,其中主要包括:

  • 聚合操作需要被定義在 hvd.elastic.run 函數(shù)下

  • 每個 worker 都有自身的狀態(tài)(state),且在訓(xùn)練之前會被同步一次

  • worker 的增減會觸發(fā)其他 worker 上的重置(reset)事件

  • 重置事件會激活以下幾個操作(不一定全部執(zhí)行): a. worker 是否應(yīng)該繼續(xù)運行 b. 將失效的 worker 列入黑名單 c. 在新的 hosts 上啟動 worker 進程 d. 更新 worker 的 rank 信息

  • 在重置事件之后,每個 worker 的狀態(tài)會被同步

在實際操作中,用戶需要向 horovodrun 提供一個 discover_hosts.sh 腳本,用以實時反饋當前可用的 hosts 以及每個 hosts 上的 slots(以下用 discover_hosts.sh 指代該腳本,但該腳本無需命名為 discover_hosts.sh)。

Horovod Elastic on Kubernetes

在 Elastic 功能推出之前,Kubeflow 社區(qū)的 MPI-Operator 是將 Horovod 部署并運行在 Kubernetes 集群上的主流方案。MPI-Operator 雖然經(jīng)歷 v1alpha1、v1alpha2 和 v1 三個版本,但大體上的思想一致。其主要過程包括:

基于AllReduce的彈性分布式使用方法是什么

  1. MPIJob Controller 會根據(jù)每一份 MPIJob 的配置,生成一個 launcher pod 和對應(yīng)個數(shù)的 worker pod

  2. MPIJob Controller 會針對每一份 MPIJob 生成一份 ConfigMap,其中包含兩份腳本,一為反應(yīng)該任務(wù)所有 worker pod 的 hostfile,一為 kubexec.sh 腳本

  3. Launcher pod 上的 mpirun 會利用由 ConfigMap 中的 kubexel 在 worker pod 中拉起進程;需要注意的是,kubectl的執(zhí)行有賴于 MPIJob Controller 預(yù)先創(chuàng)建的 RBAC 資源(如果對應(yīng)的 Role 中沒有給 launcher pod 配置在 worker pod 上的執(zhí)行權(quán)限,launcher pod 在執(zhí)行kubectl exec` 時會被拒絕)

此前,MPI-Operator 和 Elastic Horovod 存在幾個兼容性上的問題。由于 MPI-Operator 的三個版本間存在些許差異,我們這里只討論 v1 版本:

  1. MPI-Operator 尚不提供 discover_hosts.sh,這一點直接導(dǎo)致 Elastic Horovod 無法使用

  2. 當用戶將 worker replicas 調(diào)小之后,controller 不會對“額外”的 worker pod 采取任何措施,這會導(dǎo)致 worker pod 無法釋放,訓(xùn)練任務(wù)的實例規(guī)模也就無法縮小

  3. 當用戶增大 worker replica 后,controller 并不會為 launcher pod 的 Role 配置新增 worker 的執(zhí)行權(quán)限,這會導(dǎo)致 launcher pod 上的 horovodrun 在試圖利用 kubectl 在新創(chuàng)建的 worker pod 上執(zhí)行進程時被 Kubernetes 的權(quán)限管理機制拒絕

基于這些存在的兼容性問題,我們在社區(qū)上提出了 Elastic Horovod on MPIJob:https://github.com/kubeflow/mpi-operator/pull/335 。配合對 Horovod 的修改 https://github.com/horovod/horovod/pull/2199 ,能夠在 Kubernetes 上實現(xiàn) Horovod 的彈性訓(xùn)練。

在該方案中,最關(guān)鍵的問題在于如何在 launcher pod 上實現(xiàn) discover_hosts.sh 的功能。而在 Kubernetes 上實現(xiàn)該功能的關(guān)鍵,在于如何獲取當前處在 Running 狀態(tài)的 worker pods。這里有兩種思路。

  1. MPIJob Controller 構(gòu)建 discover_hosts.sh并通過 ConfigMap 同步至 launcher pod

  • MPIJob Controller 本身就在監(jiān)聽 pods 相關(guān)的信息,利用 controller 內(nèi)的 podLister,可以很快地列出每一個 MPIJob 的 worker pods;

  • 根據(jù) pods 的 status.phase,controller 在篩選出 Running 狀態(tài)的 worker pods 之后,就可以構(gòu)建出一份反映當前 worker pods 狀態(tài)的 discover_hosts.sh;

  • 通過 ConfigMap,controller 可以將 discover_hosts.shhostfile、kubexec.sh 腳本一樣同步至 launcher pod。

  • 利用 launcher pod 內(nèi)已有的 kubectl 向 APIServer 實時獲取 worker pod 信息

2.Launcher pod 自身已經(jīng)綁定了 pods 的 “get” 和 “l(fā)ist” 權(quán)限,通過 kubectl 或者其他 Kubernetes client 的直接調(diào)用,即可獲取對應(yīng) pod 信息,通過一樣的篩選標準也可以返回 Elastic Horovod 期待的信息。

考慮到第二種思路無法限制用戶執(zhí)行 discover_hosts.sh 的頻率,如果用戶執(zhí)行過于頻繁或是 MPIJob 規(guī)模較大的情況下,會對 Kubernetes 集群造成較大的壓力,第一種思路在管控上更為全面。

一種對思路二的修正是將 kubectl 或是 client 改為一個 podLister 運行在 launcher pod 中,從而降低對 APIServer 的壓力。然而這種方式使得 launcher pod 中運行了兩個進程。當這個 podLister 進程失效時,缺乏合適的機制將其重新拉起,會造成后續(xù)的彈性訓(xùn)練失效。

因此,我們提議中選擇了第一種思路,這樣一來,controller 通過 ConfigMap 將 discover_hosts.sh 同步至 launcher pod 內(nèi),并掛載于 /etc/mpi/discover_hosts.sh 下。同時,該提議中也對 controller 針對另外兩個兼容性問題做了相應(yīng)的修改。這些修改并不會影響到非 Elastic 模式的 MPI 任務(wù),用戶只需忽略 discover_hosts.sh 即可。

當然這種方案也存在一定的問題。ConfigMap 同步至 launcher pod 存在一定的延遲。然而一方面,這個延遲時間是 Kubernetes 管理員可以進行調(diào)整的。另一方面相比整個訓(xùn)練所花的時間,同時也相比 Elastic Horovod 在重置上所花的時間,這一部分延遲也是可以接受的。

彈性訓(xùn)練演示

最后,我們通過一個示例來演示如何在 Kubernetes 上運行 Horovod 彈性訓(xùn)練任務(wù)。任務(wù)創(chuàng)建的過程與普通的訓(xùn)練任務(wù)類似,即通過 MPIJob 創(chuàng)建。

bash-5.0$ kubectl create -f ./tensorflow-mnist-elastic.yaml
mpijob.kubeflow.org/tensorflow-mnist-elastic 
createdbash-5.0$ kubectl get po
NAME    READY   STATUS    RESTARTS  AGE
tensorflow-mnist-elastic-launcher   1/1     Running   0          14s
tensorflow-mnist-elastic-worker-0   1/1     Running   0          14s
tensorflow-mnist-elastic-worker-1   1/1     Running   0          14s

在示例中,我們一共創(chuàng)建了兩個 worker 參與訓(xùn)練。在訓(xùn)練開始后,調(diào)整 MPIJob.Spec.MPIReplicaSpecs["Worker"].Replicas 實例數(shù)量,增加一個新的 worker 后,觀察實例數(shù)量。新的 worker 加入訓(xùn)練,完成數(shù)據(jù)集的獲取和初始化之后,訓(xùn)練任務(wù)會不中斷地繼續(xù)訓(xùn)練。其中 discover_hosts.sh 的內(nèi)容如下:

bash-5.0$ kubectl exec tensorflow-mnist-elastic-launcher -- /etc/mpi/discover_hosts.sh
tensorflow-mnist-elastic-worker-0:1
tensorflow-mnist-elastic-worker-1:1
bash-5.0$ kubectl edit mpijob/tensorflow-mnist-elastic
mpijob.kubeflow.org/tensorflow-mnist-elastic edited
bash-5.0$ kubectl exec tensorflow-mnist-elastic-launcher -- /etc/mpi/discover_hosts.sh
tensorflow-mnist-elastic-worker-0:1
tensorflow-mnist-elastic-worker-1:1
tensorflow-mnist-elastic-worker-2:1

最后,我們再嘗試把實例數(shù)量調(diào)整為一,訓(xùn)練集群中的兩個實例會被回收,而訓(xùn)練仍然會繼續(xù)。

bash-5.0$ kubectl edit mpijob/tensorflow-mnist-elastic
mpijob.kubeflow.org/tensorflow-mnist-elastic edited
bash-5.0$ kubectl get po
NAME               READY   STATUS        RESTARTS   AGE
tensorflow-mnist-elastic-launcher   1/1     Running       0          4m48s
tensorflow-mnist-elastic-worker-0   1/1     Running       0          4m48s
tensorflow-mnist-elastic-worker-1   1/1     Terminating   0          4m48s
tensorflow-mnist-elastic-worker-2   1/1     Terminating   0          2m21s
Thu Mar 11 01:53:18 2021[1]<stdout>:Step #40    Loss: 0.284265
Thu Mar 11 01:53:18 2021[0]<stdout>:Step #40    Loss: 0.259497
Thu Mar 11 01:53:18 2021[2]<stdout>:Step #40    Loss: 0.229993
Thu Mar 11 01:54:27 2021[2]<stderr>:command terminated with exit code 137
Process 2 exit with status code 137.
Thu Mar 11 01:54:27 2021[0]<stderr>:command terminated with exit code 137
Process 0 exit with status code 137.
Thu Mar 11 01:54:57 2021[1]<stderr>:[2021-03-11 01:54:57.532928: E /tmp/pip-install-2jy0u7mn/horovod/horovod/common/operations.cc:525] Horovod background loop uncaught exception: [/tmp/pip-install-2jy0u7mn/horovod/third_party/compatible_gloo/gloo/transport/tcp/pair.cc:575] Connection closed by peer [10.244.2.27]:54432
WARNING:root:blacklist failing host: tensorflow-mnist-elastic-worker-2
WARNING:root:blacklist failing host: tensorflow-mnist-elastic-worker-1
Thu Mar 11 01:54:58 2021[1]<stdout>:Step #50    Loss: 0.207741
Thu Mar 11 01:55:00 2021[1]<stdout>:Step #60    Loss: 0.119361
Thu Mar 11 01:55:02 2021[1]<stdout>:Step #70    Loss: 0.131966

這說明通過 MPIJob 的支持,Horovod Elastic 能夠手動地擴縮容,滿足業(yè)務(wù)需要。在后續(xù)的工作中,我們會繼續(xù)支持配合 HorizontalPodAutoscaler 的自動擴縮容、指定實例的縮容等高級特性,以滿足更多的場景。

以上就是“基于AllReduce的彈性分布式使用方法是什么”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI