王 婷,陳斌岳,張福海
(南開大學(xué) 電子信息與光學(xué)工程學(xué)院,天津300350)
隨著人工智能的快速發(fā)展,卷積神經(jīng)網(wǎng)絡(luò)越來越受到人們的關(guān)注。 由于它的高適應(yīng)性和出色的識別能力,它已被廣泛應(yīng)用于分類和識別、目標(biāo)檢測、目標(biāo)跟蹤等領(lǐng)域[1]。 與傳統(tǒng)算法相比,CNN 的計(jì)算復(fù)雜度要高得多,并且通用CPU 不再能夠滿足計(jì)算需求。 目前,主要解決方案是使用GPU 進(jìn)行CNN 計(jì)算。 盡管GPU 在并行計(jì)算中具有自然優(yōu)勢,但在成本和功耗方面存在很大的缺點(diǎn)。卷積神經(jīng)網(wǎng)絡(luò)推理過程的實(shí)現(xiàn)占用空間大,計(jì)算能耗大[2],無法滿足終端系統(tǒng)的CNN 計(jì)算要求。 FPGA 具有強(qiáng)大的并行處理功能,靈活的可配置功能以及超低功耗,使其成為CNN 實(shí)現(xiàn)平臺(tái)的理想選擇。 FPGA 的可重配置特性適合于變化的神經(jīng)網(wǎng)絡(luò)網(wǎng)絡(luò)結(jié)構(gòu)。 因此,許多研究人員已經(jīng)研究了使用FPGA 實(shí)現(xiàn)CNN 加速的方法[3]。 本文參考了Google 提出的輕量級網(wǎng)絡(luò)MobileNet 結(jié)構(gòu)[4],并通過并行處理和流水線結(jié)構(gòu)在FPGA 上設(shè)計(jì)了高速CNN 系統(tǒng),并將其與CPU 和GPU 的實(shí)現(xiàn)進(jìn)行了比較。
在深度學(xué)習(xí)領(lǐng)域中,卷積神經(jīng)網(wǎng)絡(luò)占有著非常重要的地位,它的圖像識別準(zhǔn)確率接近甚至高于人類的識別水平。卷積神經(jīng)網(wǎng)絡(luò)是同時(shí)具有層次結(jié)構(gòu)性和局部連通性的人工神經(jīng)網(wǎng)絡(luò)[5]。 卷積神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu)都是類似的,它們采用前向網(wǎng)絡(luò)模型結(jié)構(gòu),節(jié)點(diǎn)使用神經(jīng)元來實(shí)現(xiàn)分層連接。 并且,相鄰層之間的節(jié)點(diǎn)是在局部區(qū)域內(nèi)相連接,同一層中的一些神經(jīng)元節(jié)點(diǎn)之間是共享連接權(quán)重的。 傳統(tǒng)的卷積神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)如圖1 所示,卷積神經(jīng)網(wǎng)絡(luò)是直接將準(zhǔn)備識別的原始圖像作為輸入,然后依次通過多個(gè)隱藏層連接到各層,得到識別結(jié)果。
圖1 卷積神經(jīng)網(wǎng)絡(luò)典型結(jié)構(gòu)
MobileNet 是用于移動(dòng)和嵌入式設(shè)備的有效模型。MobileNet 基于簡化的架構(gòu),并使用深度可分離卷積來構(gòu)建輕型深度神經(jīng)網(wǎng)絡(luò)。 為了進(jìn)一步減少參數(shù)數(shù)量并促進(jìn)在FPGA 上的部署,本文中使用了經(jīng)過修改的CNN 網(wǎng)絡(luò)結(jié)構(gòu),如圖2 所示。 共有9 個(gè)卷積層和3 個(gè)池化層。
圖2 卷積神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)
在卷積神經(jīng)網(wǎng)絡(luò)中,卷積運(yùn)算占據(jù)了大部分計(jì)算量。傳統(tǒng)的卷積分為兩個(gè)步驟,即每個(gè)卷積核與每張?zhí)卣鲌D片進(jìn)行按位乘法然后相加,此時(shí)的計(jì)算量為DF*DF*DK*DK*M*N,DF 是輸入特征圖的尺寸,DK 是卷積核的尺寸,M、N 分別是輸入通道數(shù)和輸出通道數(shù)。 本文采用的卷積方式不同于傳統(tǒng)卷積,首先按照輸入通道進(jìn)行按位相乘,得到的結(jié)果通道數(shù)是沒有變化的,接下來使用1*1 的卷積核再進(jìn)行計(jì)算,以改變通道數(shù)。這種方法的計(jì)算量為DK*DK*M*DF*DF+1*1*M*N*DF*DF, 第1 項(xiàng)表示的是卷積核為3 時(shí)的計(jì)算量,第2 項(xiàng)表示卷積核為1 時(shí)的計(jì)算量,當(dāng)DK=3 時(shí),這種卷積方式比傳統(tǒng)卷積減少了8 倍多的計(jì)算量,計(jì)算量的大幅度減少更有利于部署在資源有限的FPGA 端。 運(yùn)算一個(gè)卷積層需要6 個(gè)循環(huán)嵌套來實(shí)現(xiàn),循環(huán)順序按照輸出通道>輸入通道>高度>寬度>卷積內(nèi)核元素依次來排列計(jì)算。 對于每一卷積層來說,最外面的循環(huán)按照順序遍歷所有像素。上述循環(huán)結(jié)構(gòu)的優(yōu)化實(shí)現(xiàn)可以使用循環(huán)展開,循環(huán)拆分以及循環(huán)合并的指令方法,以設(shè)計(jì)加速器的IP 核。
在訓(xùn)練了卷積神經(jīng)網(wǎng)絡(luò)之后,參數(shù)數(shù)據(jù)是一個(gè)32 位浮點(diǎn)數(shù)。 相關(guān)實(shí)驗(yàn)已經(jīng)證實(shí),精度降低一定程度對CNN識別精度的影響非常微弱[6]。 因此,本文設(shè)計(jì)中經(jīng)過嘗試不同量化位數(shù)后,在保證了精度的情況下選擇輸入的圖像數(shù)據(jù)和權(quán)重?cái)?shù)據(jù)使用9 位定點(diǎn)數(shù)。這種設(shè)計(jì)大大降低了FPGA 資源的利用率,并提高了網(wǎng)絡(luò)運(yùn)行速度。
卷積神經(jīng)網(wǎng)絡(luò)的計(jì)算成本主要有卷積層的大量乘法運(yùn)算,在FPGA 中通常使用DSP 資源進(jìn)行乘法運(yùn)算,而通常不足的DSP 資源會(huì)成為卷積神經(jīng)網(wǎng)絡(luò)部署在FPGA 端的瓶頸。 BOOTH 算法實(shí)現(xiàn)的乘法器可有效地代替使用DSP 資源的傳統(tǒng)乘法。 在Vivado HLS 中,數(shù)據(jù)都是以十六位二進(jìn)制帶符號的補(bǔ)碼表示,原碼乘法器的移位相加方法并不能直接推廣用于補(bǔ)碼的乘法運(yùn)算中。普通的移位相加運(yùn)算量比較大,乘數(shù)的每一位都產(chǎn)生部分積,乘數(shù)中值為1 的位數(shù)決定著累加的次數(shù)。 BOOTH算法的思想是將乘數(shù)近似為一個(gè)較大的整數(shù)值,利用這個(gè)整數(shù)值與被乘數(shù)相乘的結(jié)果減去這個(gè)整數(shù)值的補(bǔ)數(shù)與被乘數(shù)相乘的結(jié)果,對于具有連續(xù)的1 和0 的乘數(shù)來說產(chǎn)生的部分積較少。 具體運(yùn)算步驟如下:
(1)被乘數(shù)X 與乘數(shù)Y 均為有符號數(shù)補(bǔ)碼,運(yùn)算結(jié)果也是補(bǔ)碼。
(2)初始部分積為0,乘數(shù)Y 末尾添加附加位,初始值為0。
(3)判斷乘數(shù)Y 后兩位:若是01 則部分積加被乘數(shù)X 再右移一位, 若是10 則部分積減被乘數(shù)X 再右移一位,若是00 以及11 則只進(jìn)行右移一位操作。
(4)累加n+1 次(n 表示數(shù)據(jù)數(shù)值位數(shù)),右移n 次。
卷積層之間的運(yùn)算有兩種實(shí)現(xiàn)模式,分為層串行模式和層并行模式[7]。 本文在設(shè)計(jì)基于FPGA 的CNN 加速器時(shí),選擇了高度的靈活性和實(shí)現(xiàn)難度低的層串行模式。
在層串行模式中,F(xiàn)PGA 中的所有PE 單元都只用于實(shí)現(xiàn)卷積神經(jīng)網(wǎng)絡(luò)中一層的功能。并且通過重復(fù)調(diào)用存在的PE 單元,即使用時(shí)分復(fù)用PE 單元的策略來實(shí)現(xiàn)整個(gè)神經(jīng)網(wǎng)絡(luò)的運(yùn)算[8]。 根據(jù)卷積神經(jīng)網(wǎng)絡(luò)單層操作的類似性原理,因此考慮由單層實(shí)現(xiàn)的層串行模式是確實(shí)可行的。 并且,在這種操作模式下,從DDR 中讀取數(shù)據(jù)傳輸給PE 單元,PE 單元計(jì)算得到結(jié)果后將其寫回到DDR,數(shù)據(jù)控制比較簡單。 然而,對于中間數(shù)據(jù)的存儲(chǔ),層串行模式是通過AXI 總線協(xié)議將每一層的中間運(yùn)算結(jié)果都再傳輸?shù)酵獠看鎯?chǔ)器DDR 中,因此這種方法對IO 帶寬的要求非常高[9]。
為了增大吞吐量并解決因帶寬瓶頸而造成的傳輸時(shí)間過長,可以減少每一層的數(shù)據(jù)訪問以及存儲(chǔ)空間,以實(shí)現(xiàn)最大程度的數(shù)據(jù)和模塊復(fù)用。 因此,本文將每三層合并為一組,然后將結(jié)果輸出到DDR,從而將12 層CNN 結(jié)構(gòu)減少為5 層,這將節(jié)省一部分傳輸步驟。 此操作將多層融合在一起而形成局部組合的方法,將從DRAM 接收的輸入數(shù)據(jù)和操作的中間結(jié)果緩存都存儲(chǔ)在片上BRAM 存儲(chǔ)器中。
在帶寬瓶頸的影響下,整個(gè)硬件平臺(tái)的加速性能主要受到數(shù)據(jù)的訪存效率限制。為了有效控制數(shù)據(jù)流的訪存將使用緩沖技術(shù),以增加帶寬利用率[10]。 乒乓操作的緩沖方式是使用兩個(gè)數(shù)據(jù)存儲(chǔ)器,先將數(shù)據(jù)存儲(chǔ)在第一個(gè)數(shù)據(jù)緩存中,當(dāng)?shù)谝粋€(gè)數(shù)據(jù)緩存存滿時(shí),數(shù)據(jù)將轉(zhuǎn)換到第二個(gè)數(shù)據(jù)緩存中存儲(chǔ),并在相同時(shí)刻讀取第一個(gè)數(shù)據(jù)緩存中的數(shù)據(jù)。這種方式使得單通道的數(shù)據(jù)傳輸有效地變化為雙通道的數(shù)據(jù)流傳輸, 數(shù)據(jù)流經(jīng)過緩沖后,不斷地傳遞到數(shù)據(jù)處理模塊,這將使數(shù)據(jù)傳輸時(shí)間與數(shù)據(jù)運(yùn)算時(shí)間重疊,以抵消大部分的時(shí)間[11]。
為了提高加速器系統(tǒng)的吞吐效率,在片內(nèi)的輸入緩存設(shè)置了圖像輸入緩存和權(quán)值輸入緩存,以及結(jié)果輸出緩存。 輸入緩存的作用是從外部存儲(chǔ)器DDR 中載入所需數(shù)據(jù)以及所需參數(shù),輸出緩存的作用是將存儲(chǔ)運(yùn)算結(jié)果輸出至外部存儲(chǔ)器DDR 中或者是再應(yīng)用于計(jì)算單元中。緩存結(jié)構(gòu)根據(jù)DMA 的方式來進(jìn)行數(shù)據(jù)交互。本文的輸入圖像、權(quán)值以及輸出的計(jì)算結(jié)果都采用如圖3 所示的乒乓緩沖方式。兩個(gè)數(shù)據(jù)緩沖模塊通過二選一復(fù)用器相互配合使用,使數(shù)據(jù)可以沒有停頓地依次加載到計(jì)算單元中,計(jì)算單元可以時(shí)時(shí)刻刻處于計(jì)算狀態(tài),以此充分利用了有限的計(jì)算資源。
圖3 乒乓緩存數(shù)據(jù)流
加速器的總體設(shè)計(jì)如圖4 所示,由PS 和PL 組成。其中PS 主要負(fù)責(zé)圖像數(shù)據(jù)預(yù)處理,權(quán)重?cái)?shù)據(jù)預(yù)處理和特征定位的任務(wù),而PL 負(fù)責(zé)整個(gè)CNN 計(jì)算部分。 加速器系統(tǒng)通過AXI 總線將CPU 和外部存儲(chǔ)器DDR 中的卷積神經(jīng)網(wǎng)絡(luò)參數(shù)權(quán)重,以及要識別的輸入圖像像素?cái)?shù)據(jù)傳遞給PL 部分。 當(dāng)操作控制指令傳遞到PL 端時(shí),PL 端啟動(dòng)系統(tǒng)主程序,并通過輸入緩沖區(qū)的乒乓操作將參數(shù)和像素?cái)?shù)據(jù)傳輸?shù)竭\(yùn)算操作邏輯單元。在完成整個(gè)卷積神經(jīng)網(wǎng)絡(luò)的計(jì)算后,輸出數(shù)據(jù)通過AXI 總線通過輸出緩沖區(qū)傳輸?shù)紻DR 存儲(chǔ)器,并輸出最終結(jié)果。
圖4 加速器系統(tǒng)的整體設(shè)計(jì)
實(shí)驗(yàn)采用Xilinx Zynq UltraScale+MPSoC ZU3EG A484 Development Board 對本文目標(biāo)檢測定位算法進(jìn)行加速。片內(nèi)由ARM 處理器與可重構(gòu)FPGA 構(gòu)成,片上資源主要 由432 個(gè)BRAM 和360 個(gè)DSP 組 成。 CPU 采 用Intel Core i5 2500K 處理器,GPU 是NVIDIA UeForce UTX 960。所用到的軟件開發(fā)工具為賽靈思公司開發(fā)的Vivado 設(shè)計(jì)套件Vivado IDE 和Vivado HLS。
傳統(tǒng)的FPGA 設(shè)計(jì)流程復(fù)雜且繁瑣,為了簡化開發(fā)流程,加速器系統(tǒng)采用高級綜合方式來進(jìn)行優(yōu)化設(shè)計(jì)[12]。首先采用Vivado HLS 開發(fā)工具將CNN 計(jì)算過程的高級編程語言C++轉(zhuǎn)化為硬件描述語言,再封裝為Vivado 的IP 核輸出。 Vivado HLS 工具具體的設(shè)計(jì)流程如圖5 所示。 然后利用Vivado IDE 開發(fā)工具,導(dǎo)入封裝好的CNN運(yùn)算IP 核、主控單元zynq_ultra_ps、時(shí)鐘單元以及AXI傳輸模塊。 通過綜合、設(shè)定約束、布局布線來實(shí)現(xiàn)完成整個(gè)加速器系統(tǒng)的設(shè)計(jì)。
圖5 Vivado HLS 工具設(shè)計(jì)流程
表1 列出了默認(rèn)乘法的FPGA 的資源使用情況,表2 列出了部分乘法用BOOTH 算法代替的資源使用情況,由于開發(fā)板的LUT 資源使用率已經(jīng)很高,因此部分乘法還是采用了DSP 資源。 BRAM 用于圖像數(shù)據(jù)、網(wǎng)絡(luò)權(quán)重及輸出數(shù)據(jù)的緩存,DSP 以及LUT 用于卷積模塊的乘加運(yùn)算,該設(shè)計(jì)高效地利用了FPGA 的內(nèi)部資源。
表1 默認(rèn)乘法FPGA 內(nèi)部資源的利用率
表2 BOOTH 乘法FPGA 內(nèi)部資源的利用率
表3 中顯示了將FPGA 中CNN 的性能與Intel Core i5 CPU 和NVIDIA UeForce UTX 960 UPU 進(jìn)行比較的結(jié)果。 基于FPGA 優(yōu)化設(shè)計(jì)的卷積神經(jīng)網(wǎng)絡(luò)處理單個(gè)圖像所需的時(shí)間比CPU 要少得多,相當(dāng)于GPU 的速度。 GPU功耗是本文設(shè)計(jì)的30 倍以上。
表3 不同硬件平臺(tái)的性能評估
本文提出了一種基于FPGA 有限資源的卷積神經(jīng)網(wǎng)絡(luò)加速器。利用BOOTH 算法實(shí)現(xiàn)乘法,有效降低了DSP 資源占用量。通過流水線結(jié)構(gòu)和卷積運(yùn)算的并行性提高了卷積運(yùn)算的速度。網(wǎng)絡(luò)加速器的內(nèi)部結(jié)構(gòu)在資源有限的開發(fā)板上實(shí)現(xiàn)12 層CNN 網(wǎng)絡(luò), 并將其與CPU 和GPU進(jìn)行比較。 實(shí)驗(yàn)結(jié)果表明,嵌入式FPGA 的功耗和性能具有很大的優(yōu)勢,更適合于移動(dòng)端的部署。