滿 濤,郭子豪,曲志堅
(山東理工大學 計算機科學與技術學院,山東 淄博 255049)
隨著計算機視覺和深度學習的迅速發展和廣泛應用,對于卷積神經網絡(Convolutional Neural Network,CNN)的關注度越來越高。但是,隨著CNN的網絡深度和規模越來越大,由此帶來的功耗較大和計算效率低等問題又使得人們關注于使用不同架構的硬件來加速CNN的計算[1-3]。對于CNN,現場可編程門陣列(Field Programmable Gate Array,FPGA)使用軟硬件協作來執行CNN網絡,可重構配置以便在速度、功耗和靈活性之間權衡,可以大大提高計算效率并降低功耗。
目前的研究主要針對CNN模型的壓縮和終端推理計算的設計與優化。在模型壓縮方面,Choi等[4]分別對目標權重和激活分別量化并形成一個整體量化神經網絡(Quantized Neural Network,QNN)的新技術;Ding等[5]提出使用2的冪的有限組合替代權重,從而用移位操作代替乘累加操作,實現了更高的準確性和更快的速度。在FPGA的設計與優化方面,Zhang等[6]設計了一種對特征圖分塊展開的加速方法并提出Roofline模型優化資源利用率,Li等[7]設計了一種單指令多數據(Single Instruction Multiple Data,SIMD)的卷積與流水線結構進行CNN加速,Stylianos等[8]提出一種以同步數據流(Synchronous Dataflow,SDF)計算模型為基礎的加速器框架,Yang等[9]使用移位操作和1×1卷積優化網絡設計了新的加速器架構和CNN模型。
本文針對使用浮點數進行卷積計算導致的計算復雜度高、模型占用空間大和運算速度慢的問題,設計了一種基于FPGA的卷積神經網絡加速器。首先,通過設計動態定點量化方法,實現了將浮點CNN模型各層的權值和特征圖參數動態量化為定點模型;其次,通過輸入即輸出方式的流水線架構提高數據吞吐率,并對卷積運算單元進行并行優化以提升計算效率;最后,采用MNIST手寫數字字符庫和CIFAR-10數據集進行方案和功能驗證。
CNN是由大量具有可學習功能參數(也稱為“權重”)執行點積的神經元構建的,并且需要反向傳播進行訓練并向前傳播進行測試。CNN與傳統識別算法不同,其輸入數據可以使用圖像,并且不再需要特征提取和數據重建。在此條件下,CNN的前向傳播等效于二維卷積,這意味著CNN具有很強的確定性和并行性便于對其加速。經典的CNN模型由許多不同的層組成,特征圖依次在這些層上進行運算,下一層都從上一層的輸出中讀取輸入特征,然后執行和輸出。常用的CNN層包括卷積層、池化層、全連接層和分類層。
LeNet-5是一個非常成功且典型的卷積神經網絡模型[10],其網絡結構如圖1所示。

圖1 LeNet-5網絡結構圖
對于MNIST數據集,LeNet-5網絡的輸入為28×28×1大小像素的圖片,對于CIFAR-10數據集,該網絡的輸入為32×32×3大小像素的圖片。輸入圖像按照網絡結構的順序依次通過conv1-pool1-conv2-pool2-fc1-fc2層后輸出10個特征值,然后在softmax層中進行歸一化求出最大概率值,進而得出分類結果。兩個數據集的網絡參數設置如表1所示。

表1 網絡參數表
采用ARM+FPGA的整體架構設計卷積神經網絡的前向推斷加速,包括ARM處理器部分(Processing System,PS)和FPGA邏輯資源部分(Programmable Logic,PL)。因為卷積神經網絡的計算密集層主要為卷積層和全連接層,所以進行軟硬件劃分時,在FPGA上實現的主要是網絡的運算,而ARM處理器主要負責對輸入數據和參數進行預加載和分配,并執行對FPGA初始階段的控制。
系統的結構框架如圖2所示。左上方為ARM處理器PS部分,灰色區域為可編程邏輯PL部分。PS部分主要包括ARM雙核處理器及其控制的數據輸入端口、分類結果輸出端口、DDR(Double Data Rate)存儲模塊和IP(Internet Protocol)網絡接口,PL部分主要由AXI_DMA控制模塊、片上存儲器和由不同層的IP核構成的CNN硬件加速器組成。

圖2 系統結構框圖
系統的具體工作流程如下:ARM Cortex-A9處理器通過IP網絡接口從上位機獲取MNIST數據集或CIFAR-10數據集的特征圖和權值參數數據并存入到DDR存儲模塊中,然后驅動AXI_DMA模塊,從直接存儲寄存器(Direct Memory Access,DMA)中將特征圖和權值參數傳輸到片上存儲器(Random Access Memory,RAM)。ARM會控制CNN硬件加速器模塊從片上存儲器中讀取所需的特征圖和權重參數數據進行計算,在CNN加速模塊計算完之后將計算結果存儲在片上存儲器中。整個運算過程完畢之后,ARM會驅動AXI_DMA模塊,將運算結果從片上存儲器傳輸到DMA再傳輸到DDR存儲器中,ARM通過IP網絡接口將結果傳輸給上位機。
CNN硬件加速器模塊的實現是通過將卷積神經網絡的各個層設計成IP核,然后將各層IP核按照網絡的結構連接到一起,通過AXI4-Streaming總線來傳輸數據流,各層之間采用輸入即輸出的計算模式。該計算模式實現了流水線操作,數據流可以由每個層獨立地驅動,上一層計算好的數據可以立即傳出,既節省了整個網絡的內存占用又提高了系統魯棒性。
為了減少FPGA在計算時的資源耗費,在網絡模型識別準確率保持不變或者略微下降的前提下,一般采用數據量化來降低網絡模型計算時的數據位寬[11]。文獻[12]從優化CNN運行內存帶寬角度出發,統計了CNN分別采用浮點數與定點數計算時MNIST手寫數字數據集的識別錯誤率,其測試結果顯示數據在使用定點16位和定點32位時錯誤率基本沒有變化。
在FPGA上進行卷積計算時大部分使用乘法器和加法器進行設計。乘法器和加法器的資源消耗與數據精度息息相關。根據實驗得出,乘法器和加法器主要耗費數字信號處理器(Digital Signal Processing,DSP)和查找表(Look-up Table,LUT)資源。不同精度下,乘法器和加法器的資源耗費如表2所示。

表2 資源耗費比較
表2表明,選擇浮點32位精度設計單個乘法器和加法器時,DSP和LUT消耗都比較大。然而,定點數16位精度的加法器不消耗DSP,只消耗較少的LUT;乘法器的資源消耗也大大減少。因此,在確保數據精度不變或較少變化的前提下,定點計算具有很大的優勢。
文獻[13-14]介紹了對于網絡模型參數和輸入輸出特征圖的采用動態定點數量化的方法。本文借鑒了相關的量化思路,設計并采用16位動態定點數對卷積神經網絡中的參數和特征圖進行量化,如圖3所示。在對每一層的輸入輸出特征圖和權重參數進行量化時,采用階碼來表示每一層參數和特征圖分配給小數部分的位數,每一層的階碼是固定的,層與層之間的階碼是根據數據分布范圍動態調整的。

圖3 動態定點量化
動態定點量化定點數xfixed由以下公式表示:
(1)
式中:s表示符號位,f表示階碼,B表示量化的位寬長度,xi表示尾數部分。定點數xfixed最高位為符號位。
動態定點數量化包含以下三個部分:
(1)參數量化
在進行量化之前,需要先找到每層權重參數的最優階碼fw:
fw=argmin|Xfloat-Xfw|。
(2)
式中:Xfloat表示在CNN訓練中某層權重參數的原始浮點值,Xfw表示在給定階碼fw的情況下對Xfloat定點化后再轉換回浮點數的值。在CNN原始的浮點數權重和定點量化后的權重差的值最小的情況下得出的fw為該層的最優階碼。
(2)中間特征圖量化
其次,需要按照網絡的結構對網絡中每層的輸入輸出特征圖進行量化,使得每層特征圖具有共同的階碼fo,其滿足
fo=argmin|Pfloat-Pfo|。
(3)
式中:Pfloat表示CNN前向推斷中的輸出特征圖的原始浮點數值,Pfo表示給定階碼fo的情況下對原始數據定點化后再轉回浮點數的值。其余過程與參數量化類似。
(3) 中間參數量化
在對權重參數和中間特征圖進行定點量化之后,還需要對中間的計算結果進行量化。采用乘加和移位的方式對CNN中間計算產生的定點數進行操作,保證卷積神經網絡在FPGA上的數據計算和傳輸都采用定點數來進行。中間參數量化的階碼fm的計算公式如下:
fm=argmin|Mfloat-Mfm|。
(4)
由以上的量化計算公式可得LeNet-5模型的階碼如表3所示。CNN模型進行計算時采用量化后的參數進行運算,對定點數進行乘累加運算,將運算結果按照每層的階碼再進行量化操作,量化后的特征圖再作為下一層的輸入參與到下一層的計算,直到完成CNN模型所有的計算。

表3 CNN各層階碼
ARM端的一個任務是負責從DDR內存到FPGA片上存儲器的數據傳輸,通過AXI_DMA模塊實現。通過AXI4-Lite總線對AXI_DMA模塊進行配置,對DDR存儲模塊的指定區間執行讀寫任務,DMA通過AXI4總線讀取DDR內的特征圖數據,并通過AXI4-Streaming總線將讀取到的數據輸入片上緩存模塊,進而給到CNN加速IP,并將最后的結果通過總線接收后傳輸至ZYNQ處理系統,完成數據的傳輸。
進行數據傳輸的總線使用了握手協議更為簡單的AXI4-Streaming總線。AXI4-Streaming總線協議去除了地址概念,不再是一種地址映射協議,而是數據流通信協議,可以始終不斷地對一個地址讀寫,因此該協議主要面向高速的、大數據量的數據流傳輸,這提高了數據傳輸的效率。存儲器直接訪問DMA是一種高速的數據傳輸操作,在存取數據的過程中,數據的傳輸由FPGA上的獨立控制器控制和調度,這樣CPU和其他功能模塊可以負責其他任務。通過使用AXI4-Streaming協議和直接存儲寄存器DMA可以為系統提供更高的數據傳輸吞吐量。
為了減少存儲器傳輸延遲,本設計將所有的特征圖數據和權重參數都存儲在片上存儲器中,在運行時可以重新加載。
本文設計了如圖4所示的卷積計算單元,將卷積計算單元設計為多個部分,包括存儲模塊、移位寄存器、乘法器陣列、加法樹和累加器,一方面通過將數據存儲在多個存儲模塊中來同時獲取多個數據;另一方面是將復雜的卷積運算轉換成乘加法運算,需要使用較多的DSP資源來提升并行性。

圖4 卷積計算單元
為了減少緩沖區的使用和提高計算的吞吐量,采用了不改變滑窗計算過程并且使用較少DSP資源的乘加樹計算方法。該卷積層輸入多張特征圖及其對應權重,分別經過乘累加運算后得到一組卷積結果。對該組結果進行相加后,得到一個卷積計算的輸出,然后對結果進行緩存。設計的卷積計算單元能夠將多個特征圖計算并行,從結構的層面對卷積神經網絡并行加速。
由于塊隨機存取存儲器(Block Random Access Memory,BRAM)的限制,無法把所有數據都存入到BRAM上進行計算,若通過DDR讀取傳入數據再進行計算,則速度會受到影響。在設計時提出將輸入特征圖存儲于基于LUT的存儲模塊中,權重存儲于基于BRAM的存儲模塊中,通過添加約束指令來實現對于存儲模塊的分割,以便于并行獲取多個輸入數據。
如圖4所示,有4個存儲模塊輸入特征圖1~4負責存儲輸入特征圖,4個存儲模塊權重參數1~4負責存儲權重。對于包含填充操作的卷積神經網絡,需在輸入特征圖的邊緣位置填充0。根據當前卷積操作所在的時鐘周期,負責執行點積的數據被存入移位寄存器Ai和Bi中,然后使用4個乘法器陣列對權值和特征圖進行乘法運算,將計算值共享給加法樹進行累加計算,最后的累加器負責將上一層的輸出的值求和,結果再經過之后的非線性函數ReLU送到下一層。在計算的過程中不用等待當前計算完成再獲取下一組數據,而是在下一個時鐘周期繼續獲取數據,構成一個數據處理流水線。因此,整個卷積計算模塊具有高吞吐量,從而整體的數據處理速度也得到提高。
本文設計的池化模塊如圖5所示,通過5個for循環遍歷輸入通道、輸入特征圖長寬和卷積核大小,并可根據模型選擇三種池化方式。

圖5 池化運算單元
平均值池化一般由輸入數據和一個系數恒定的系數乘加實現,最大值和最小值池化由比較器實現。池化的步長為2,窗口尺寸為2×2,以類似滑動窗口的方式來進行池化操作。
本文進行硬件設計使用的開發板是Xilinx公司的PYNQ-Z2,該開發板使用的是ZYNQ-7000 xc7z020clg400-1的FPGA芯片。實驗中的硬件開發環境為Vivado 2019.1和Vivado HLS 2019.1。在通用的CPU平臺上用軟件實現了與FPGA完全一致的CNN模型,CPU采用的是Inter Core i5-8300H處理器,主頻為2.3 GHz,卷積神經網絡的訓練和執行采用基于Python的Tensorflow 1.15框架。實驗的測試數據集是MNIST數據集和CIFAR-10數據集。
通過PYNQ開源框架,用戶可以可直接在PYNQ-Z2上進行開發和測試。本設計所采用的基于PYNQ的測試流程如下:
Step1 在Vivado開發環境中對設計的方案進行綜合、布局布線、生成bit和tcl文件,給FPGA上電并啟動。
Step2 給DDR存儲模塊加載網絡參數和數據集。
Step3 通過PYNQ進行SoC編程,Overlay比特流,配置FPGA。
Step4 對測試集中的圖片進行識別,識別完成后FPGA輸出識別結果,ARM處理器從PL端讀回測試結果,并通過IP網絡接口傳至上位機。
Step5 如果當前批次中的圖片未處理完,則重復操作Step 4;如果測試完成,記錄識別時間并傳至上位機。
在文獻[15-16]中,使用16位定點數量化進行模型壓縮導致的識別準確率的下降范圍為0.02%~2.88%。不同批次下,本文采用數據量化的方法進行模型壓縮后的準確率如表4所示,在MNIST數據集下由數據量化引入的精度損失不超過0.6%,在CIFAR-10數據集下由數據量化引入的精度損失范圍是0.5%~1.4%。

表4 不同批次下準確率對比
在批次為500的情況下,本文將數據量化后的參數代替原有的參數在軟件平臺進行測試后發現,對于MNIST數據集卷積神經網絡的識別準確率從98.6%降低到98.4%,對于CIFAR-10數據集卷積神經網絡的識別準確率由75.3%降低至74.2%,可見是由數據量化的使用導致了準確率的下降。經過FPGA實現后,兩個數據集的識別率仍為98.4%和74.2%,說明硬件實現并未導致新的識別精度的下降。
本次設計經過綜合、布局布線后,Vivado 2019.1給出的資源使用情況如圖6所示,圖中列出了LeNet-5模型在MNIST數據集和CIFAR-10數據集下FPGA的資源使用情況。

圖6 FPGA資源消耗
通過對FPGA資源使用情況分析可以發現,BRAM、LUT和DSP48乘法器是本設計占用率比較大的資源。由于本文使用的方法是將權值參數全部放在片上BRAM中,特征圖的值存儲在基于LUT的存儲模塊上,所以對于BRAM和LUT的資源使用率非常高。對于乘法部分運算邏輯全部使用的DSP資源。可以看出,本設計對資源的利用率很高。
由于文獻[17-20]并未給出功耗及性能指標,對于功耗方面,本文按照對比文獻中的時鐘頻率和資源使用率,使用Xilinx Power Estimator(XPE)得出其FPGA的運行功耗;對于性能方面,本文按照文獻[21]中的關于計算量的公式對其進行了計算以方便對比,CNN中的計算量指的是輸入一張圖像,CNN網絡模型進行一次完整的前向傳播所發生的浮點運算次數,也即模型的時間復雜度,單位為FLOPs。而GFLOPS是指每秒十億次浮點運算的次數,表示計算的速度,與GOPS近似相等,是一種衡量硬件性能的指標,所以本文使用GFLOPS來進行性能分析。單個卷積層的計算如公式(5)所示:
FLOPs=2×Ho×Wo×K2×Cin×Cout。
(5)
式中:Ho、Wo表示每個卷積核輸出特征圖的高度和寬度;K表示每個卷積核的邊長;Cin表示每個卷積核的通道數,也即輸入通道數;Cout表示本卷積層擁有的卷積核數,也即輸出通道數。
對于全連接層,浮點運算次數計算公式如下:
FLOPs=2×I×O。
(6)
式中:I表示全連接層輸入維度,O表示輸出維度。
根據表5列出的實驗結果,本文的硬件工作平臺FPGA的工作頻率為100 MHz,識別每張圖片的時間為MNIST數據集2.067 ms和CIFAR-10數據集4.98 ms,且功耗僅為1.6 W左右。識別時間在Jupyter notebook中可視化的時間損耗為計算時間,包括網絡部署時間、Python腳本解釋器初始化時間、內存傳輸以及前向傳播的時間。

表5 相關工作比較
此外,通過本次設計的板級測試,得到系統的性能等數據與其他文獻的對比,如表5所示。文獻[17-20]與本文設計比較類似,均研究了在FPGA上實現小型網絡的加速方案,文獻[17-18]使用的是MNIST數據集,文獻[19-20]使用的是CIFAR-10數據集。通過比較,文獻[17]使用的數據精度更低,但本文在單幀時間、功耗及性能方面更優。文獻[18]在單幀時間及性能方面均優于本文設計,但其使用了1 180個DSP,使用的DSP數量約是本文設計的9.2倍,但在性能方面僅為本設計的1.9倍,本文在單位DSP的性能貢獻方面優于該文獻。文獻[19]雖然在功耗方面與本文相近,但是本文在性能方面為其15.7倍,能效比方面為其15.5倍。文獻[20]使用了32位浮點數,其單幀時間、性能和能效比方面都不如本設計。綜上所述,本文設計的FPGA加速方案具有更好的綜合性能。
表6為本文設計所使用的開發平臺與同等網絡結構下CPU和GPU性能對比。由表6可知,本設計實現的FPGA加速器功耗僅為文獻[22]中CPU和GPU的5.8%和6.6%,性能方面相比也有較大的提升。

表6 與CPU、GPU的比較
為了解決目前硬件設備上實現卷積神經網絡資源有限和功耗過大問題,本文提出了一種基于流水線架構的卷積神經網絡加速器架構。該架構針對CNN網絡的結構設計卷積計算策略,并在FPGA平臺上量化了網絡參數,解決了卷積神經網絡需要大量FPGA資源進行計算的問題。為了優化內存,本文提出了一種CNN各層輸入即輸出的工作方式,各層IP按照流水線的方式工作,大大提高了數據交互效率。本設計在xc7z020上實現了LeNet-5,實驗結果表明,與LeNet-5在CPU、GPU和其他FPGA平臺中的實現相比,本文提出的方法保持了準確率,節省了資源,降低了功耗,對資源和功耗有限的平臺實現卷積神經網絡的加速具有重要意義。
為了進一步提高FPGA加速器的性能,后續的研究方向主要集中在探索模型壓縮的算法并設計更大更復雜的加速器,提升FPGA硬件架構的通用性。