[深度学习] 分布式Horovod介绍(四)
[深度學習] 分布式模式介紹(一)
[深度學習] 分布式Tensorflow介紹(二)
[深度學習] 分布式Pytorch 1.0介紹(三)
[深度學習] 分布式Horovod介紹(四)
?
實際應用中,單機多卡的同步式數據并行是最常用的,在論文中最常見的訓練方式是單機八卡. 數據再多一般就需要多機多卡.
無論是單機多卡,還是多機多卡,均是分布式訓練,在horovod出現之前,使用tensorflow,一般只有官方推薦的集群訓練方式。
可是tensorflow的集群訓練,用起來并不輕松
Tensorflow集群的缺點
1. 概念多,學習曲線陡峭
tensorflow的集群采用的是parameter server架構,因此引入了比較多復雜概念,羅列如下
server client master cluster parameter server worker job task replica_device_setter master service worker service clone涉及到的函數
tf.train.Server tf.train.Supervisor tf.train.SessionManager tf.train.ClusterSpec tf.train.replica_device_setter tf.train.MonitoredTrainingSession tf.train.MonitoredSession tf.train.SingularMonitoredSession tf.train.Scaffold tf.train.SessionCreator tf.train.ChiefSessionCreator tf.train.WorkerSessionCreator反復研究過多次,還是沒有徹底弄清楚,server,client,master,master service,worker service,clone,session之間的關系。 大致是,在client中創建server實例,session與server一一對應,server內含master service和worker service兩個服務,master service負責與外界通訊,比如sess.run一般都是告訴server的master service要開始工作了,server的master service通知同一個server的worker service去干活,worker service調動GPU運算,完成后,返回結果給master service,做權值更新,如果是多機多卡的分布式,parameter server與master service之間做梯度傳遞和權值同步。 stackoverflow.com/questions/3…
2. 修改的代碼量大
如果想把單機單卡的模型,移植到多機多卡,涉及的代碼量是以天記的,慢的話甚至需要一周。
3. 需要多臺機子跑不同的腳本
tensorflow集群是采用parameter server架構的,要想跑多機多卡的集群,每個機子都要啟動一個client,即跑一個腳本,來啟動訓練,100個機子,人就要崩潰了。
4. ps和worker的比例不好選取
tensorflow集群要將服務器分為ps和worker兩種job類型,ps設置多少性能最近并沒有確定的計算公式。
5. 性能損失較大
tensorflow的集群性能并不好,當超過一定規模時,性能甚至會掉到理想性能的一半以下。
?
Horovod
由于Tensorflow集群太不友好,業內也一直在嘗試新的集群方案。 2017年Facebook發布了《Accurate, large minibatch SGD: Training ImageNet in 1 hour 》驗證了大數據并行的高效性,同年百度發表了《Bringing HPC techniques to deep learning 》,驗證了全新的梯度同步和權值更新算法的可行性。受這兩篇論文的啟發,Uber開發了Horovod集群方案
Horovod 是 Uber 開源的又一個深度學習工具,本文將簡要介紹這一框架的特性。
隨著 Uber 在 TensorFlow 上訓練越來越多的機器學習模型,項目的數據和計算能力需求正在急劇增加。在大部分情況下,模型是可以在單個或多 GPU 平臺的服務器上運行的,但隨著數據集的增大和訓練時間的增長,有些時候訓練需要一周甚至更長時間。因此,Uber 的工程師們不得不尋求分布式訓練的方法。
Uber 開始嘗試部署標準分布式 TensorFlow 技術,在試驗了一些方法之后,開發者意識到原有方法需要進行一些調整:首先,在遵循文檔和代碼示例之后,我們并不總是清楚哪些功能對應著哪些模型訓練代碼的分布式計算。標準分布式 TensorFlow 引入了很多新的概念:工作線程、參數服務器、tf.Server()、tf.ClusterSpec()、 tf.train.SyncReplicasOptimizer() 以及 tf.train.replicas_device_setter() 等等。它們在某些情況下能起到優化作用,但也讓我們難以診斷拖慢訓練速度的 bug。
第二個問題有關 Uber 規模的計算性能。在進行了一些基準測試之后,我們發現標準的分布式 TensorFlow 機制無法滿足需求。例如,在使用 128 個 GPU 進行訓練時,我們因為低效率損失了一半的計算資源。
?
約定如下: 網絡帶寬記為:B(單位Mb/s), 模型總參數數據量記為:D(單位Mb), 總服務器數量記為:n, 參數服務器數量記為:n_p(其中有n= n_p+ n_w), worker服務器數量記為:n_w(其中有n= n_p+ n_w) 單服務器計算一次耗時記為:T_0
梯度同步和權值更新算法
1) parameter server架構
tensorflow的集群架構是parameter server架構,數據的傳導模型如下圖。
?
?
則可以計算出,parameter server架構的集群方案,總耗時:
?
?
可以看出T與總節點數n基本成線性關系,但不同的參數服務器和woker服務器分配方案,總性能也將不同。 假設,e表示worker服務器占比,即e=n_w/n,則可以計算出最優的e值為:
?
?
可以看出,最優worker服務器占比與模型大小、網絡帶寬、單機運行時間都有關系,并不是一個一眼能最優值得超參數。
2)horovod的ring-allreduce算法
百度2017年發表的《Bringing HPC techniques to deep learning 》中,采用了全新的梯度同步和權值同步算法,叫做ring-allreduce。此種算法各個節點之間只與相鄰的兩個節點通信,并不需要參數服務器。因此,所有節點都參與計算也參與存儲。 一次權重更新,主要包含兩個過程, 1)累計梯度 將所有梯度分為n個片段,每次只與相鄰節點傳遞1個片段的梯度,n-1次后,每一片段的梯度都完成了所有節點這一片段梯度的累計,但不用片段的累計值分布在不同節點上。如下圖的第2、第3步; 2)將累計后的梯度分發到所有節點 將第一步累計的梯度再次通過n-1次的相互交換后,所有節點的梯度完成同步。如下圖的第4、第5步。再平均后,更新權重,就完成了所有節點權重的更新。
?
?
可以計算出ring-allreduce算法的總耗時為:
?
可以看出,總耗時基本與總節點數n成線性關系(n較大時,1/n基本為0)
Horovod的梯度同步和權值同步就采用了ring-allreduce算法。
概念
horovod的數據傳遞是基于MPI,因此其涉及的概念也是MPI中的概念。以4個服務器,每個服務器4個GPU為例,
- size 進程數量,也即所有GPU數量,為16
- rank 進程的唯一ID,0-15
- local rank 每一個server中的進程的本地唯一ID,0-3
- allreduce 累加所有數據,并同步到所有節點的操作,如下圖
?
?
?
- allgather 收集所有數據,并同步到所有節點的操作,完成后每個節點都包含所有節點的數據,并且這些數據單獨存在。如下圖。
?
?
?
- broadcast 將數據(需要由根節點確認)從一個節點傳播到其他所有節點的操作
?
?
?
大概就這么多概念,簡單清晰。
將單機單卡改為多機多卡
將一個只支持單機單卡的訓練腳本修改為支持多機多卡的訓練腳本,以tensorflow為例,只需要做如下改動:
import tensorflow as tf import horovod.tensorflow as hvd# Initialize Horovod hvd.init()# Pin GPU to be used to process local rank (one GPU per process) config = tf.ConfigProto() config.gpu_options.visible_device_list = str(hvd.local_rank())# Build model... loss = ... opt = tf.train.AdagradOptimizer(0.01 * hvd.size())# Add Horovod Distributed Optimizer opt = hvd.DistributedOptimizer(opt)# Add hook to broadcast variables from rank 0 to all other processes during # initialization. hooks = [hvd.BroadcastGlobalVariablesHook(0)]# Make training operation train_op = opt.minimize(loss)# Save checkpoints only on worker 0 to prevent other workers from corrupting them. checkpoint_dir = '/tmp/train_logs' if hvd.rank() == 0 else None# The MonitoredTrainingSession takes care of session initialization, # restoring from a checkpoint, saving to a checkpoint, and closing when done # or an error occurs. with tf.train.MonitoredTrainingSession(checkpoint_dir=checkpoint_dir,config=config,hooks=hooks) as mon_sess:while not mon_sess.should_stop():# Perform synchronous training.mon_sess.run(train_op)可以看出,改動不大,只需添加10行左右的代碼,主要分為6步:
1)初始化horovod
hvd.init()2)一個GPU與一個進程綁定
config = tf.ConfigProto() config.gpu_options.visible_device_list = str(hvd.local_rank())3)根據總GPU數量放大學習率
opt = tf.train.AdagradOptimizer(0.01 * hvd.size())因為BatchSize會根據GPU數量放大,所以學習率也應該放大
4)使用hvd.DistributedOptimizer封裝原有的optimizer
opt = hvd.DistributedOptimizer(opt)分布式訓練涉及到梯度同步,每一個GPU的梯度計算仍然由原有的optimizer 計算,只是梯度同步由hvd.DistributedOptimizer負責。
5)廣播初始變量值到所有進程
hooks = [hvd.BroadcastGlobalVariablesHook(0)]主要為了確保所有進程變量初始值相同
6)只在worker 0上保存checkpoint
checkpoint_dir = '/tmp/train_logs' if hvd.rank() == 0 else None防止checkpoint保存錯亂
horovod只是需要改動必要改動的,不涉及parameter server架構的device設置等,繁瑣的操作。
開始訓練
在單機4卡的機上起訓練,只需執行以下命令:
horovodrun -np 4 -H localhost:4 python train.py在4機,每機4卡的機子上起訓練,只需在一個機子上執行以下命令即可:
horovodrun -np 16 -H server1:4,server2:4,server3:4,server4:4 python train.py注意無論是單機多卡,還是多機多卡,都只需在一個機子上執行一次命令即可,其他機horovod會用MPI啟動進程和傳遞數據。
性能對比
?
?
?
horovod隨著規模增大,性能損失遠小于tensorflow,基本是線性增加的。
Horovod 問題
- checkpoint 的保存與恢復
只需要將 Worker 0 的checkpoint保存即可, 重啟恢復的時候 Worker 0 的參數會通過hvd.BroadcastGlobalVariablesHook(0) 傳播到其他 Worker
- horovod Failures due to SSH issues
執行horovodrun命令的主機必須能夠免密通過SSH登陸到其他主機,
參考 SSH login without password
- 更多問題請見Troubleshooting
結論
通過Tensorflow集群的人,會深刻體會到horovod有多好用,感謝百度、Facebook和Uber讓深度學習更美好。
不過,也要注意到,horovod的分布式貌似只支持同步更新式的數據并行,模型并行和異步更新式的數據并行,我沒有嘗試過,根據ring-allreduce算法可知,應該是不支持的。
?
鏈接:是時候放棄tensorflow集群投入horovod的懷抱
?
總結
以上是生活随笔為你收集整理的[深度学习] 分布式Horovod介绍(四)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [深度学习] PyTorch-BigGr
- 下一篇: [深度学习] 分布式Tensorflow