關於caffe的python寫的層多GPU訓練


關於caffe的python寫的層多GPU訓練

http://blog.csdn.net/chengqishang110/article/details/52355986

之前訓練faster的時候一直沒有辦法進行多GPU訓練,以為是自己的錯,今天看了/include/caffe/layers/python_layer.h發現原來這是caffe的緣故。 
python_layer.h 
原來caffe在寫的時候就不允許python使用多GPU訓練。

深入分析:

其是主要的是python的緣故。 
這里提到一個GIL。這里的GIL是 Python 的Global Interpreter Lock (全局解釋器鎖) 一次只允許一個thread在python解釋器中運行。

什么是全局解釋器鎖呢?

Python代碼的執行由Python虛擬機(也叫解釋器主循環)來控制。Python在設計之初就考慮到要在主循環中,同時至於一個線程在執行,就像但CPU的系統中運行多個進程那樣,內存中可以存放多個程序,但在任意時刻,只有一個程序在CPU中運行。同樣地,雖然Python解釋器可以“運行”多個線程,但在任意時刻,只有一個線程在解釋器中運行。

對Python虛擬機的訪問由全局解釋器鎖(global interpreter lock GIL)來控制,正是這個鎖能保證同一時刻只有一個線程在運行。在多線程環境中,Python虛擬機按以下方式執行。

  1. 設置GIL
  2. 切換到一個線程運行。
  3. 運行: 
    a. 指定數量的字節碼的指令,或者 
    b. 線程主動讓出控制(可以調用time.sleep(0))

  4. 把線程設置為睡眠狀態。

  5. 解鎖GIL。
  6. 再次重復以上所有步驟。 
    在調用外部代碼(如C/C++擴展函數)的時候,GIL將會被鎖定,知道這個函數結束為止(由於在這期間沒有Python的字節碼被運行,所以不會有線程切換)。編寫拓展的程序員可以主動解鎖GIL。不過,Python的開發人員則不用擔心在這些情況下你的Python代碼會被鎖住【1】。

那解決辦法是什么呢?就這樣認命么?NO!

高手總是有的。

方案1:https://github.com/BVLC/caffe/issues/2936 
提供者:naibaf7 Berkeley Vision and Learning Center member 
release the GIL for the forward/backward passes in the OpenCL branch。

方案2:https://github.com/BVLC/caffe/pull/4360 
提供者:alessandroferrari 
Added ScopedGILRelease for easy GIL release. Modified _caffe.cpp in pycaffe accordingly.

參考文獻: 
【1】Python核心編程(第二版)

 

====================================================================================================================================================================================================

http://www.caffecn.cn/?/question/85

現在的caffe版本已經支持多GPU並行了,原理比較簡單,就是每個GPU分別算一個batch,n個GPU,實際的batchsize就是n*batch,比如原來用一個GPU,batchsize設置成256,現在用4個GPU,把batchsize設置成64,和原來的一個GPU的運算是等價的。
 
實際使用的時候基本不用設置,和原來一樣編譯好就可以用了。命令就是在-gpu 后面對多個GPU號用逗號隔開,比如-gpu 1,2,3,4 就是同時使用1-4共4個GPU,GPU編號可以不連續,或者直接用-gpu all,就是使用所有的GPU。
 
官方的github里是這樣寫的

1.jpg


正好我也在用順手截圖

2.jpg


可以看到輸出的log里提示了使用了兩個GPU

如果你原來的batchsize是32 現在兩個GPU 就改成16

====================================================================================================================================================================================================

我有三個顯卡,當我使用命令 -gpu all時會出錯,而使用-gpu 0,2時能正常運行,但是在log輸出力我看到了
I0119 09:22:49.801615  8412 parallel.cpp:245] GPU 2 does not have p2p access to GPU 0
這個信息,意思是不是有問題?源碼是parallel.cpp里的

好像2個GPU的話,組成[-1,0;0,1]兩個pairs,GPU樹深為1,構建兩個sync,四個的話就是[-1,0;0,1;2,3;0,2],GPU樹深為2,構建4個sync,三個的話應該是不行的,5個應該也是不行。。。奇數不行。。。而 I0119 09:22:49.801615 8412 parallel.cpp:245] GPU 2 does not have p2p access to GPU 0 這個輸出跟GPU的個數沒關系

====================================================================================================================================================================================================

https://www.zhihu.com/question/53580158

問:我用-gpu 0,-gpu 2和-gpu 0,2這三種的運行時間幾乎一樣,好像並沒有什么並行加速效果

支持多GPU並行訓練。但是單次迭代所用時間會略微加長,caffe並行主要用來拓展minibatch大小的。

問:也就是說是在保證精度的前提下,提高minibatch,從而加速???可以這樣理解嗎??

caffe只能這么並行提高minibatch size,把一個epoch耗時縮減到原來的 顯卡數分之一。因為單次更新參數使用的樣本大量增加,可以適當提高下學習率並讓它加速衰減。

問:我測試下來GPU數量越多速度越慢。。什么鬼。。

卡數越多會導致梯度同步的耗時變大,目前caffe只提供了簡單的p2p同步,一定程度上解決大網絡單卡訓練顯存不足的情況,對於訓練速度上沒有什么優化。

====================================================================================================================================================================================================

http://blog.csdn.net/u011394059/article/details/74528849

在訓練center-loss 網絡時,center-loss 太大,雖然乘以一個很小的系數(0.008),還是導致loss特別大,最后loss為87.3365,為nan。 
不斷調整參數,最后可以訓練了,然后看輸出: 
這里寫圖片描述 
在gpu 0 和gpu 2之間沒有p2p 交互。 
stackoverflow上的problem1,說性能會下降,因為沒有用到 SLI bridge,只會導致訓練速度的下降,不會帶來其他的問題;problem2。 
找到了官方的文檔multi-gpu解釋,在使用多GPU時,性能會跟最差的那一個一致,並且是,實際的batchsize數為網絡文件中的batchsize*gpu個數。 
沒開 p2p dma access 會導致計算性能下降。 
使用nvidia-smi topo -m查看, 
這里寫圖片描述

====================================================================================================================================================================================================

https://www.zhihu.com/question/59321480

需要重做dataparallel,寫bn的kernel,以及用nccl cross gpu通信

 

作者:張航
鏈接:https://www.zhihu.com/question/59321480/answer/198077371
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

終於搞定了Synchronized BatchNorm,來回答一下這個問題。

首先針對問題本身,目前所有的framework,包括Caffe,Torch,TF,PyTroch等等,BatchNorm的實現都是只考慮了single gpu。也就是說BN使用的均值和標准差是單個gpu算的,相當於縮小了mini-batch size。至於為什么這樣實現,1)因為沒有sync的需求,因為對於大多數vision問題,單gpu上的mini-batch已經夠大了,完全不會影響結果。2)影響訓練速度,BN layer通常是在網絡結構里面廣泛使用的,這樣每次都同步一下GPUs,十分影響訓練速度。

 

關於如何實現,這里不得不寫一下心得,從發現問題到實現synchronize,花了將近一周的時間,一開始把這個問題想簡單了,希望對大家有所幫助吧。偶然中發現自己做的task十分依賴synchronzie BN (因為在公司實習, 不方便說project)。然后開始實現:

1。 因為通常訓練過程是將網絡復制到不同的gpu上,然后進行forward和backward,之后只需要collect gradient,再更新主gpu上的網絡,然后下一個iteration再復制一遍。在這種方式下,不同gpu的BN layer是沒辦法通信的。所以第一步是重做了DataParallel架構,可以enable 每層的通信。

2。 第二步就是推推公式,相信各位大神花點兒時間動動筆就搞定,我就不贅述了。然后開始編程寫kernel,核心思想是每次forward 時候sync一下均值和方差,然后backward的時候sync一些grad of 均值和方差,再繼續backward。

3。本身前兩步搞定之后,應該一切順利了,可是訓練的時候總是跑幾十個iteration就卡死。這個其實是pytorch autograd engine 的問題, 因為每個BN layer的均值和方差都是cross gpu 的grad graph,而我們又是大量使用BN,所以成個back-prop的graph破壞了pytorch grad engine。解決方案是寫一個cross gpu的autograd function來handle。

大體思路是這樣的,可能發paper的時候再release。不過大部分task應該不涉及這個題。


低調地update一下,我已經公開了這個PyTorch implementation, 大家可以先用,我過幾天放個arxiv paper,鏈接: Synchronized BatchNorm

 

請問,synchronize對訓練速度的影響具體是怎樣的?

張航
張航 (作者) 回復openblack (提問者)4 個月前
您問的是實現的效率問題嗎,我的implemention,4卡是時候慢了20%,主要慢在了synchronization上了
GuangxingHan
GuangxingHan3 個月前

請問一下BN的均值和方差是通過moving average計算得到的把?需要在反向傳播時更新grad嗎?

張航
張航 (作者) 回復GuangxingHan3 個月前

是當前batch的running均值和方差,accumulated均值和方差只在inference的時候用,請參考這個博客Understanding the backward pass through Batch Normalization Layer

lixin liu
lixin liu2 個月前

請問是基於什么框架實現的?

張航
張航 (作者) 回復lixin liu2 個月前

用PyTorch寫的

lixin liu
lixin liu回復張航 (作者)2 個月前
需要改框架底層?
張航
張航 (作者) 回復lixin liu2 個月前
需要重做dataparallel,寫bn的kernel,以及用nccl cross gpu通信
Huaijin
Huaijin28 天前

你好, 這個有效果的對比嗎?采用多GPU的的BN和無同步的BN對比。

張航
張航 (作者) 回復Huaijin19 天前
上大網,比如resnet152,不sync gpu很影響效果,每個gpu只能過2張圖


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM