1. 程式人生 > >caffe CPU模式下訓練速度很慢

caffe CPU模式下訓練速度很慢

前面提到了利用caffe訓練模型時,只用單個CPU核的問題,通過openblas的方式解決了,但即使多個核用上了,但速度還是超級慢。


就目前使用的網路而言,1min只能跑30 iter(1個iter 128個樣本),即30*128 = 3840 樣本/min, 為什麼如此之慢呢?是不是程式碼出了問題,或者哪裡的設定不對?


嘗試和lenet進行對比,利用8核CPU根據lenet訓練mnist,大概8min完成10000iter(一個iter 64個樣本),即10000*64/8 = 80000 樣本/min


從這裡的對比來看,lenet的訓練速度還是正常的,網上也有提出訓練lenet花費了10min左右。那麼為什麼速度差別這麼大呢?應該是網路計算量的原因。


通過https://dgschwend.github.io/netscope/#/editor可以檢視網路的計算量,在左側輸入網路的deploy.prototxt檔案即可,然後按shift + enter即可檢視網路的計算量。
分析發現lenet網路的計算量為2.29M,而我們的網路的計算量為36.08M,這樣就分析清楚了,3840*36.08 = 138547.2,而80000*2.29 = 183200,還是比較接近的。因此訓練的速度應該就是這樣了。


另外又將caffe下的訓練速度和tensorflow下的訓練進行對比,發現很奇怪的事情


  tensorflow    caffe
 GPU 700 iter/min1500 iter/min 
 CPU 200 iter/min20 iter/min 
難道caffe的CPU速度如此之慢?還不明白是為啥。




再做一次實驗,在tensorflow和caffe利用mnist資料集訓練lenet網路(網路結構根據caffe中的example修改,另外寫一個tensorflow的lenet網路),看一下耗時。
得到的資料如下:
用mnist訓練lenet, 10000 iter, 每個batch 64個樣本


  GPU + CPU CPU 核數無限制 CPU 8核
 tensorflow 50s 219s 258s
 caffe 30s 1000s+
 900s


從這裡可以看出,caffe在GPU模式下確實速度會比tensorflow快,但CPU模式下的速度卻要慢很多。(這裡有個問題就是caffe在CPU模式下用的核越多,速度卻變慢了,這個問題其他人也有提到,不明所以)




查資料,有提到說openblas需要用OpenMP編譯,即使用openblas的多執行緒形式,有可能預設通過apt-get下載安裝的openblas並沒有使用了openmp。在前面的部落格提到了如何安裝openblas以及使用cpu的多核進行訓練。


1、首先對比一下通過apt-get安裝的openblas和自己編譯安裝的openblas的區別
通過 sudo apt-get install libopenblas-dev安裝的openblas在預設目錄/usr/lib下,可以通過ldd命令檢視其使用的so庫,結果如下
-Bash 程式碼
1
ldd /usr/lib/libopenblas.so
2
 
3
linux-vdso.so.1 =>  (0x00007fffb435a000)
4
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa84028b000)
5
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa84006d000)
6
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa83fca3000)
7
/lib64/ld-linux-x86-64.so.2 (0x0000560783ce6000)


再手動編譯安裝openblas
 
首先從https://github.com/xianyi/OpenBLAS下載openblas,
然後unzip OpenBLAS-xxx,
再 make USE_OPENMP=1
再sudo make install
即把openblas安裝到了 /opt/OpenBLAS目錄下


安裝好之後,
-Bash 程式碼
01
ldd /opt/OpenBLAS/lib/libopenblas.so
02
 
03
linux-vdso.so.1 =>  (0x00007fffe6988000)
04
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f3876368000)
05
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f387614a000)
06
libgfortran.so.3 => /usr/lib/x86_64-linux-gnu/libgfortran.so.3 (0x00007f3875e2f000)
07
libgomp.so.1 => /usr/lib/x86_64-linux-gnu/libgomp.so.1 (0x00007f3875c20000)
08
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3875857000)
09
/lib64/ld-linux-x86-64.so.2 (0x000055933fb64000)
10
libquadmath.so.0 => /usr/lib/x86_64-linux-gnu/libquadmath.so.0 (0x00007f387561a000)
11
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f3875404000)


由此可見通過自己編譯安裝的openblas,再呼叫了libgomp等其它的庫。


2、通過openblas編譯caffe


通過apt-get安裝的openblas,預設在/usr/lib中,因此編譯caffe,修改caffe中的Makefile.config中的BLAS即可,再編譯即可
但要使用自己編譯的openblas來編譯caffe,在Makefile.config中有個blas的lib和include的目錄設定,但設定後,不能有效


最終通過export LD_LIBRARY_PATH=/opt/OpenBLAS/lib才搞定,


再用ldd build/lib/libcaffe.so, 就可以看到這裡面用的是/opt/OpenBLAS/lib中的so庫。




3、再看一下兩者的訓練速度對比


通過apt-get安裝的方式,openblas可以設定OPENBLAS_NUM_THREADS=N來設定使用多少個CPU核
而通過自己編譯安裝的openblas,則可以設定OMP_NUM_THREADS=N來設定使用多少個程序


通過OMP_NUM_THREADS來設定,會發現,基本無效,用1個程序,用4個程序和用8個程序,速度基本無變化




尷尬啊,這個問題還是解決不了啊




參考博文:
Caffe:CPU模式下使用openblas-openmp(多執行緒版本) http://blog.csdn.net/10km/article/details/52723306




就caffe使用openblas+openmp,設定OMP_NUM_THREADS,訓練速度卻不能提升的問題,進行調研,沒有太好的解決方案,在網上看到有說程序加速依賴於網路結構,有些網路結構可以加速,有些不行。也有說設定OMP_NUM_THREADS=1就好。眾說紛紜,不知所以然。




如果這條路走不通,那麼可能的解決方案有如下幾個:


1、OPENMP的加速方案,有人在caffe提交了pull request,據說可以加速5-10倍,https://github.com/BVLC/caffe/pull/439,但caffe沒有接受該PR,為了程式碼的穩定性


2、intel版本的caffe,據說是做過加速的,可能存在的問題:(1)、是否收費,有沒有用intel的MKL庫,這個庫應該是收費的,(2)、產品需要做開原始碼的認證(intel的caffe版本,我司應該沒有做過認證)(https://software.intel.com/en-us/articles/comparison-between-intel-optimized-caffe-and-vanilla-caffe-by-intel-vtune-amplifier)


3、再退回到tensorflow,用tensorflow的c/c++ API,存在問題:(1)、tensorflow的C/C++訓練模型,參考較少;(2)、tensorflow的c/C++未實現auto differentiation?


4、再轉戰其它框架,抓狂






目前寄希望於在caffe中使用MKL庫和使用intel優化的caffe版本。




前面碰到的一個就是通過設定OMP_NUM_THREADS無效果,設定它的值越大,訓練速度越慢,設定一個較小的值時,反而訓練速度更快,做了一些嘗試,發現如果用adam優化運算元,則設定OMP_NUM_THREADS無效果,如果用其它的則有效,通過把adam運算元替換,再設定OMP_NUM_TRHEADS=8時大概會有3倍速度的提升。
-Bash 程式碼
1
base_lr: 0.001
2
momentum: 0.9
3
momentum2: 0.999
4
 
5
lr_policy: "fixed"
6
type: "Adam"
-Bash 程式碼
1
base_lr: 0.001
2
momentum: 0.9
3
 
4
lr_policy: "step"
5
gamma: 1
6
stepsize: 5000


但上面的配置涉及到學習率調整的問題,以及引數的微調,沒能達到和Adam一樣的準確率。


那麼開始轉戰使用intel的mkl庫,以及intel的caffe版本。


使用intel的caffe版本主要參考這個intel出的效能對比說明  
Benefits of Intel® Optimized Caffe* in comparison with BVLC Caffe*
https://software.intel.com/en-us/articles/comparison-between-intel-optimized-caffe-and-vanilla-caffe-by-intel-vtune-amplifier


在這裡,說明了,使用intel的caffe+mkl,可以達到多大效能的提升。




首先來看一下,如何在原生的caffe中使用intel的mkl庫。


mkl庫和atlas、openblas的功能一致,需要下載安裝後,在caffe中的makefile.config檔案中進行配置即可。
下載mkl庫,需要先到intel網上進行註冊申請,https://software.intel.com/en-us/mkl。申請後,一般會受到一封郵件,裡面包含了註冊碼等資訊,然後再申請一個intel的賬號,就可以下載mkl了,會得到類似“l_mkl_2018.1.163.tgz”檔名的mkl壓縮包,之後就可以進行安裝了。但是我申請了,等了四五天都沒有收到郵件,不知道哪裡有問題,可以找其他同事也試一試。


下載安裝檔案後,在Ubuntu下解壓縮,tar -xvzf l_mkl_2018.1.163.tgz, 進入到解壓後的目錄下,執行./install.sh 根據提示操作,完成mkl庫的安裝,安裝後,預設在/opt/intel目錄下會有mkl的lib和include。


完成mkl庫的安裝,然後就是重新編譯caffe。


在caffe的主目錄下,配置Makefile.config, 修改BLAS的內容,如下:


-Bash 程式碼
1
BLAS := mkl
2
BLAS_INCLUDE := /opt/intel/mkl/include
3
BLAS_LIB := /opt/intel/mkl/lib/intel64


另外,在編譯caffe,和openblas類似,也需要匯入lib庫到LD_LIBRARY_PATH,因此先執行
-Bash 程式碼
1
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/intel/mkl/lib/intel64


再make clean, make all -j32,就可以完成編譯了。
再用ldd build/tools/caffe 可以看到依賴於libmkl_rt.so這個庫了。
但是隻是用mkl庫編譯原生的caffe,訓練速度提升不明顯,感覺和OpenBLAS開多個執行緒的區別不大。提升很有限。


那麼繼續嘗試intel的caffe版本,首先需要下載intel的caffe 原始碼,


git clone https://github.com/intel/caffe


(這裡需要確保git clone正常可以用,後面在編譯intel-caffe的時候也需要用到,會下載mkl-dnn的原始碼等)
然後配置Makefile.config檔案,和之前使用mkl庫的方式一樣,配置blas為mkl。然後就開始make就行了。


如果是通過windows下載了intel-caffe,然後拷貝到linux上,再解壓,可能會有些.sh檔案無執行許可權,編譯時會出錯。




如果編譯無誤了後,就可以開始執行了,可以發現,確實速度有很大的提升,大概相比於原生的caffe有7-8倍速度的提升,和intel官方給的資料可能有一點偏差,主要是用原生的caffe+mkl的速度沒有intel官方說的那麼慢。


但我在訓練我的網路碰到了一些問題,準確率不上升,但是用caffe自帶的網路結構訓練mnsit和cifar10,是沒有問題。


一開始檢查發現,intel-caffe會預設有一些網路結構的優化,在src/caffe/net.cpp中,去掉優化後,還是有問題,於是重新開始搭建網路結構,一層一層的搭,發現增加第三個卷積層,就會出錯,完全相同的網路結構,完全相同的資料,但在intel-caffe和原生的caffe表現不同,intel-caffe開始訓練不動,準確率不上升了。百思不得其解,也無從下手解決該問題,機緣巧合發現,稍微修改下網路結構有效,即將第三個卷積核的大小從5改為9或11,就好了,一切正常。


這個問題,可能比較奇怪,也不知道怎麼解決,大多人數人應該不會遇到吧。


好的,這樣子,就可以用intel加速後的caffe版本了。速度確實快了不少。