關於caffe的python寫的層多GPU訓練
http://blog.csdn.net/chengqishang110/article/details/52355986
之前訓練faster的時候一直沒有辦法進行多GPU訓練,以為是自己的錯,今天看了/include/caffe/layers/python_layer.h發現原來這是caffe的緣故。
原來caffe在寫的時候就不允許python使用多GPU訓練。
深入分析:
其是主要的是python的緣故。
這里提到一個GIL。這里的GIL是 Python 的Global Interpreter Lock (全局解釋器鎖) 一次只允許一個thread在python解釋器中運行。
什么是全局解釋器鎖呢?
Python代碼的執行由Python虛擬機(也叫解釋器主循環)來控制。Python在設計之初就考慮到要在主循環中,同時至於一個線程在執行,就像但CPU的系統中運行多個進程那樣,內存中可以存放多個程序,但在任意時刻,只有一個程序在CPU中運行。同樣地,雖然Python解釋器可以“運行”多個線程,但在任意時刻,只有一個線程在解釋器中運行。
對Python虛擬機的訪問由全局解釋器鎖(global interpreter lock GIL)來控制,正是這個鎖能保證同一時刻只有一個線程在運行。在多線程環境中,Python虛擬機按以下方式執行。
- 設置GIL
- 切換到一個線程運行。
-
運行:
a. 指定數量的字節碼的指令,或者
b. 線程主動讓出控制(可以調用time.sleep(0)) -
把線程設置為睡眠狀態。
- 解鎖GIL。
- 再次重復以上所有步驟。
在調用外部代碼(如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里是這樣寫的
正好我也在用順手截圖
可以看到輸出的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對訓練速度的影響具體是怎樣的?
請問一下BN的均值和方差是通過moving average計算得到的把?需要在反向傳播時更新grad嗎?
是當前batch的running均值和方差,accumulated均值和方差只在inference的時候用,請參考這個博客Understanding the backward pass through Batch Normalization Layer
請問是基於什么框架實現的?
用PyTorch寫的
你好, 這個有效果的對比嗎?采用多GPU的的BN和無同步的BN對比。