如果對(duì)深度學(xué)習(xí)有所了解的小伙伴們想必都知道,深度學(xué)習(xí)需要使用強(qiáng)大的服務(wù)器、加速嵌入式平臺(tái)(如NVIDIA的Jetson)來(lái)運(yùn)行深度學(xué)習(xí)算法,然而這也同樣意味著不菲的開(kāi)支。
那么問(wèn)題來(lái)了,如果你想你想用樹(shù)莓派來(lái)做一個(gè)目標(biāo)跟蹤器,為你看家守院,這可以實(shí)現(xiàn)嗎?換句話說(shuō),如果你需要在不帶加速器的ARM CPU上運(yùn)行卷積神經(jīng)網(wǎng)絡(luò)了怎么辦?
如何優(yōu)化推理時(shí)間?
本文將嘗試回答一個(gè)簡(jiǎn)單的問(wèn)題:什么庫(kù)/工具包/框架可以幫助我們優(yōu)化訓(xùn)練模型的推理時(shí)間?本文只討論已為ARM架構(gòu)芯片提供C / C ++接口的工具包和庫(kù)(由于嵌入式設(shè)備上使用 ,我們很少Lua 或 Python),限于文章篇幅,不闡述另外一種加速神經(jīng)網(wǎng)絡(luò)推理的方法,即修改網(wǎng)絡(luò)架構(gòu),從SqeezeNet架構(gòu)可看出,修改網(wǎng)絡(luò)架構(gòu)是一個(gè)可行的方案。基于上述原因,本文涉及的實(shí)驗(yàn)只涉及使用Caffe,TensorFlow和MXNet這3個(gè)開(kāi)源的深度學(xué)習(xí)框架。
加速神經(jīng)網(wǎng)絡(luò)模型在硬件平臺(tái)計(jì)算速度,兩個(gè)主要有大的策略:
1)修改神經(jīng)網(wǎng)絡(luò)的模型;
2)加快框架運(yùn)行速度。
當(dāng)然,將這兩個(gè)策略結(jié)合起來(lái)使用,也是一種不錯(cuò)的思路。
修改神經(jīng)網(wǎng)絡(luò)模型有兩種方法,一是通過(guò)降低權(quán)重精度實(shí)現(xiàn),即降低特征量化的精度,二是通過(guò)權(quán)重剪枝來(lái)實(shí)現(xiàn),權(quán)重剪枝的背后的思想是降低系統(tǒng)參數(shù)的冗余。降低權(quán)重低精度通常采用(用定點(diǎn)數(shù)或動(dòng)態(tài)定點(diǎn)數(shù)表示浮點(diǎn)數(shù)的方法,支持這種做法的原理是:推理過(guò)程并不需要高精度,因?yàn)樵谶\(yùn)算過(guò)程中,計(jì)算的線性性質(zhì)和非線性的動(dòng)態(tài)范圍壓縮,使得量化誤差僅在子線性地(sub-linearly)范圍內(nèi)傳遞,從而不會(huì)引起數(shù)值的劇烈變動(dòng)。更進(jìn)一步,我們可以使用低精度乘法來(lái)訓(xùn)練神經(jīng)網(wǎng)絡(luò)模型。結(jié)合 SIMD 指令集,比如 SSE3,可以使特征量化過(guò)程可以更為高效,從而加速訓(xùn)練過(guò)程。然而,目前我們還很難找到同時(shí)使用了這兩者的解決方案。比如使用Ristretto框架可以執(zhí)行有限精度的自動(dòng)量化,但它卻并沒(méi)有降低計(jì)算負(fù)載。TensorFlow 也可以執(zhí)行量化,但其推理時(shí)間實(shí)際上卻增加了 5 到 20 倍,因?yàn)門(mén)ensorFlow還引入了輔助量化/去量化的計(jì)算節(jié)點(diǎn)。因此在實(shí)際操作中,我們只把量化作為壓縮網(wǎng)絡(luò)權(quán)重的方法,當(dāng)存儲(chǔ)空間有限時(shí)可以這樣操作,至少這已經(jīng)是當(dāng)前最先進(jìn)的技術(shù)。
從另外一個(gè)角度看,我們可采用加快框架的執(zhí)行時(shí)間的方法,這種方法不會(huì)影響到模型的參數(shù)。這種策略主要上采用優(yōu)化矩陣之間的乘法(GEMM)類(lèi)的通用計(jì)算技巧,從而同時(shí)影響卷積層(其計(jì)算通常是 im2col+ GEMM)和全連接層。除此之外,可以使用神經(jīng)網(wǎng)絡(luò)的加速包NNPACK,就個(gè)人理解,NNPACK的核心思路是使用快速傅里葉變換將時(shí)間域中的卷積運(yùn)算轉(zhuǎn)換成了頻域中的乘法運(yùn)算。
加快框架執(zhí)行速度另一種方法是將網(wǎng)絡(luò)模型和權(quán)重配置轉(zhuǎn)換成針對(duì)目標(biāo)平臺(tái)代碼,并對(duì)代碼進(jìn)行優(yōu)化,而不是讓它們直接在某一個(gè)框架內(nèi)運(yùn)行。這種方法的典型案例是 TensorRT。還有 CaffePresso, 可以將 Caffe中prototxt類(lèi)型的文件定制成適用于各種不同硬件平臺(tái)的低規(guī)格版本。然而,TensorRT的運(yùn)行需要CUDA,而且只能在 NVIDIA的 GPU中才能使用,而 CaffePresso 也需要某種硬件加速器(DSP、FPGA或NoC)上述內(nèi)容仔細(xì)地評(píng)估現(xiàn)有的解決辦法后,我發(fā)現(xiàn)以下幾種方法能夠加速當(dāng)前流行的可用模型的推理:
如果你的框架中使用了 OpenBLAS(基礎(chǔ)線性代數(shù)程序集的開(kāi)源實(shí)現(xiàn)),你可以嘗試使用其為深度學(xué)習(xí)進(jìn)行過(guò)優(yōu)化的分支: https://github.com/xianyi/OpenBLAS/tree/optimized_for_deeplearning
NNPACK 能和其他一些框架(包括 Torch、Caffe 和 MXNet)聯(lián)合使用:http://github.com/Maratyszcza/NNPACK
將TensorFlow編譯為在樹(shù)莓派平臺(tái)的目標(biāo)代碼時(shí),你可以使用一些編譯優(yōu)化標(biāo)志,從而充分利用NEON 指令集加速目標(biāo)代碼的執(zhí)行速度:http://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/makefile#raspberry-pi
基于以上3種方法,我概括出以下調(diào)測(cè)配置:
1. 使用以 OpenBLAS為后端的Caffe 主分支(caffe-openblas);
2. 使用以 OpenBLAS為后端OpenBLAS 且為深度學(xué)習(xí)優(yōu)化過(guò)的Caffe分支版本(caffe-openblas-dl);
3. 編譯TensorFlow時(shí),使用優(yōu)化編譯標(biāo)志 OPTFLAGS="-Os" (tf-vanilla)
4. 編譯TensorFlow時(shí),使用優(yōu)化編譯標(biāo)志 OPTFLAGS="-Os -mfpu=neon-vfpv4 -funsafe-math-optimizations -ftree-vectorize" (tf-neon-vfpv4)
5. 使用以O(shè)penBLAS實(shí)現(xiàn)基礎(chǔ)線性代數(shù)程序集的Vanilla MXNet
6. 使用帶有 OpenBLAS 、且為深度學(xué)習(xí)優(yōu)化過(guò)MXNet 分支版本(mxnet-openblas-dl)。
你可能會(huì)疑惑:配置中怎么沒(méi)有 NNPACK?這確實(shí)有點(diǎn)復(fù)雜,由 ajtulloch 創(chuàng)建的 Caffe 分支提供了最直接的使用 NNPACK方法。然而自從它被集成進(jìn)去以后,NNPACK 的API接口 就已經(jīng)改變了,并且目前我無(wú)法編譯它。Caffe2 對(duì) NNPACK 有原生支持,但我不會(huì)考慮 Caffe2,因?yàn)樗幱趯?shí)驗(yàn)性階段并且?guī)缀鯇?duì)Caffe進(jìn)行了尚未文檔化的重構(gòu)。另外一個(gè)選項(xiàng)就是使用Maratyszcza的caffe-nnpack分支,但該分支比較老舊且已經(jīng)停止維護(hù)。
另外一個(gè)問(wèn)題就是出于NNPACK本身。它只提供了Android/ARM平臺(tái)的交叉編譯配置,并不提供在 Linux/ARM 平臺(tái)上的交叉編譯配置。結(jié)合MXNet,我嘗試編譯目標(biāo)平臺(tái)代碼,但結(jié)果無(wú)法在目標(biāo)平臺(tái)上正常運(yùn)行。我只能在臺(tái)式電腦上運(yùn)行它,但是我并沒(méi)有看到比 OpenBLAS 會(huì)有更好的性能。由于我的目標(biāo)是評(píng)估已經(jīng)可用的解決方法,所以我只能推遲NNPACK 的實(shí)驗(yàn)了。
以上所有的這些方法都是在四核 1.3 GHz CPU 和 1 GB RAM 的樹(shù)莓派 3 上執(zhí)行。操作系統(tǒng)是 32 位的 Raspbian,所以檢測(cè)到的 CPU 不是 ARMv8 架構(gòu),而是 ARMv7 架構(gòu)。硬件規(guī)格如下:
model name : ARMv7 Processor rev 4 (v7l)
BogoMIPS : 38.40
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xd03
CPU revision : 4
為了評(píng)估上述每個(gè)測(cè)試配置的性能,我制定的測(cè)試方案如下:使用相同的神經(jīng)網(wǎng)絡(luò)。也就是一個(gè)有 3 個(gè)卷積層和2個(gè)全連接層且在頂層帶有Softmax的小型卷積神經(jīng)網(wǎng)絡(luò):
conv1: 16@7x7
relu1pool1: MAX POOL 2x2conv2: 48@6x6
relu2pool2: MAX POOL 3x3conv3: 96@5x5
relu3fc1: 128 unitsfc2: 848 units
softmax
該卷積神經(jīng)網(wǎng)絡(luò)有 1039744 個(gè)參數(shù)。雖然非常小,但它已經(jīng)足夠強(qiáng)大了,可以用來(lái)處理許多計(jì)算機(jī)視覺(jué)算法。該網(wǎng)絡(luò)使用 Caffe 進(jìn)行訓(xùn)練人臉識(shí)別任務(wù),并將其轉(zhuǎn)換為 TensorFlow 和 MXNet 格式,從而使用這些框架進(jìn)行評(píng)估。批量執(zhí)行次數(shù)對(duì)性能有很大的影響,為了測(cè)量前向通過(guò)時(shí)間(forward pass time),我們將批量執(zhí)行的次數(shù)設(shè)置為 1 到 256。在不同次數(shù)的批量執(zhí)行中,我們每次執(zhí)行 100 次前向通過(guò),并計(jì)算了每一張圖像的平均處理時(shí)間。
評(píng)估結(jié)果和討論
在下面的表格中,列出了平均前向通過(guò)的時(shí)間。其中,A 是 caffe-openblas, B 是 caffe-openblas-dl, C 代表 tf-vanilla, D 是 tf-neon-vfpv4, E 是 mxnet-openblas, F 是 mxnet-openblas-dl。
表1 不同測(cè)試配置在不同的批處理次數(shù)下的性能表現(xiàn)
圖1 線性尺度下不同配置的前向通過(guò)時(shí)間比較
在對(duì)數(shù)尺度尺度上我們?cè)賮?lái)看一下:
圖2 對(duì)數(shù)尺度下不同配置的前向通過(guò)時(shí)間比較
測(cè)試結(jié)果讓我大吃一驚。首先,我沒(méi)有預(yù)料到在 CPU 上運(yùn)行 MXNet的性能會(huì)這么差。但這看起來(lái)已經(jīng)是一個(gè)眾所周知的問(wèn)題。此外,受限于存儲(chǔ)空間,它無(wú)法運(yùn)行 256 張圖片的批處理。第二個(gè)驚奇是優(yōu)化過(guò)的 TensorFlow 竟有如此好的性能。它甚至比 Caffe 的表現(xiàn)還好(批處理次數(shù)超過(guò)2時(shí)),光從原始框架上看是很難預(yù)料這個(gè)結(jié)果的。需要注意的是,上述測(cè)試配置中的優(yōu)化標(biāo)志并不是在任意 ARM 芯片上都可以使用的。
Caffe因速度非常快和思路獨(dú)到而知名。如果你需要連續(xù)地處理圖片,可以選擇使用優(yōu)化過(guò)的OpenBLAS的Caffe,可得到最好的處理性能。如果想提升10ms 的性能,你所要做的就只是簡(jiǎn)單的輸入以下指令:
cd OpenBLAS
git checkout optimized_for_deeplearning
為了將我的研究轉(zhuǎn)變成正式的東西,我仍需要做大量的工作:評(píng)估更多的模型,最終集成 NNPACK,以及研究更多結(jié)合了BLAS 后端的框架。
-
神經(jīng)網(wǎng)絡(luò)
+關(guān)注
關(guān)注
42文章
4804瀏覽量
102628 -
計(jì)算機(jī)視覺(jué)
+關(guān)注
關(guān)注
9文章
1706瀏覽量
46536 -
深度學(xué)習(xí)
+關(guān)注
關(guān)注
73文章
5554瀏覽量
122418
原文標(biāo)題:基于ARM在cpu上做神經(jīng)網(wǎng)絡(luò)加速
文章出處:【微信號(hào):gh_c472c2199c88,微信公眾號(hào):嵌入式微處理器】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
評(píng)論