韋蘇倫,陶青川
(四川大學電子信息學院,成都 610065)
作為一種人工神經網絡,卷積神經網絡被廣泛應用于圖像、語音識別[1]等各種智能識別系統。隨著卷積神經網絡的發展,各種各樣的網絡層出不窮,并且被應用到越來越復雜的場景當中。但隨著網絡復雜性的增加以及隨之而來的龐大計算量,運行卷積神經網絡的計算設備也需要更好的性能。傳統的CPU 并不適用于矩陣運算占主導的模型訓練和推理,GPU 雖然滿足這一特性,但對于一些嵌入式設備來說還需要更低的功耗[2]。FPGA 作為可編程邏輯器件,具有功耗低、性能高、靈活性好的特點,因此更加適用于卷積神經網絡硬件加速的開發研究[3],Verilog 開發門檻比較高,開發周期相對較長,這極大影響了卷積神經網絡在FPGA中部署的普及。
軟件工程師們應該更多考慮的是大的架構,而非某個單獨部件或逐周期運行,HLS 工具[4]的出現也是源自于此,它是一種代碼綜合技術,具體是指采用C、C++等高級編程語言進行程序編寫,而不是傳統的Verilog 語言,這大大提高了FPGA 的開發速度。本文應用HLS 高層次綜合工具,基于輕量化的原則選擇了Mobile?Netv2 網絡,在賽靈思的FPGA 開發板Kria KV260 上實現了一個卷積神經網絡加速器,通過數據的串并轉換,充分利用AXI 總線帶寬,利用pingpong 緩存技術實現數據的讀寫與計算的并行操作,同時在卷積計算中使用分組分塊計算進一步提高推理的速度。
本文使用賽靈思的Kria KV260 FPGA 開發板作為實驗板卡,Kria KV260 是賽靈思專為AI視覺設計的入門級FPGA 開發板。它的設計是一種模塊化的設計方式,分為FPGA 板卡以及接口部分,其中FPGA 板卡部分是K26 SoM,它采用Zynq UltraScale+ MPSoC 架構,包含4 核ARM Cortex-A53 處理器,提供256 K 個系統邏輯單元和1.2 K 個DSP 單元。在軟件開發環境方面,使用賽靈思的統一軟件平臺Vitis 以及高層次綜合工具Vivado HLS作為編譯測試環境。
神經網絡模型方面使用的是MobileNetv2[5]。作為經典輕量化網絡的MobileNet,自誕生就被廣泛應用于工業界。它是一種構造體量小、低延時的網絡結構,對于很多移動和嵌入式設備的圖像應用都比較適合。MobileNet 是由谷歌團隊提出的應用于移動端或者嵌入式設備中的輕量級神經網絡,在準確率只有極小幅降低的情況下,大量減少參數與運算量。MobileNet 的特點是提出了深度可分離卷積,其還可被拆分成兩個子模塊:逐通道卷積(depthwise convolu?tion)與逐點卷積層(pointwise convolution)。

表1 KV260板卡資源

圖1 KV260開發板俯視圖
對于傳統卷積來說,若卷積核大小為Dk,數量為N,圖像的尺寸為Df,圖像和卷積核的通道深度為M,那么對于N個卷積操作來說,總的計算量如公式(1)所示。
而對于深度可分離卷積神經網絡來說,其計算量包括逐通道卷積和逐點卷積兩部分,如公式(2)、(3)、(4)所示。
其中,CostDW和CostPW分別為
所以可計算出傳統卷積與深度可分離卷積的計算量比值,由公式(5)可知,后者的計算效率明顯高于傳統卷積。
MobileNetv2 是MobileNetv1 的升級版,在MobileNetv1 的深度可分離卷積基礎上,新增加了線性瓶頸和倒殘差結構,其中倒殘差結構如圖2所示。

圖2 MobileNetv2倒殘差結構
在倒殘差結構中,先用小的1*1 卷積升維,通過3*3 的逐通道卷積提取特征,最后再使用1*1 卷積降維,呈兩頭小、中間大的梭型結構。為了提升精度,在倒殘差結構中,前兩個激活函數使用ReLU6 來代替ReLU,最后使用線性激活函數。
本文的總體設計基于vivado HLS 高層次綜合[6]和PYNQ 平臺[7]。由HLS 工具通過C++語言實現卷積神經網絡的IP 核,通過仿真和綜合之后可以打包zip 核文件,通過vivado 平臺導入HLS 的zip 文件進行塊設計、布線和整體編譯得到硬件平臺的.bit 和.hwh 文件,這是PL 部分的設計。PS 端可以使用C++語言在Vitis 中進行主機端的代碼編寫或者使用Python 語言在PYNQ中進行編寫,進而控制數據的輸入與輸出并與PL 部分進行計算與交互,其數據傳輸的結構如圖3所示。

圖3 數據傳輸結構
首先通過S_AXI_lite 接口將主機端與FPGA相連接,通過讀取和寫入S_AXI_lite 端的控制寄存器來控制PL 端的行為,一般用來傳輸控制和狀態寄存器以及讀寫的地址等。對于輸入的圖像數據、權重和偏置等數據則使用存儲器映射接口M_AXI 來進行傳輸,M_AXI 存儲器映射接口可以支持最高4 K字節的突發量,并且具有獨立的讀取和寫入的通道,因此單個接口也可以同時執行讀取和寫入的操作。在傳輸讀寫地址之后,通過M_AXI接口將經過主機端映射存到全局存儲器中的數據讀取至PL內核中進行計算。
為了加快推理速度,可以進行BN 融合,即將BN 層參數和卷積層參數融合在一起,這樣在模型訓練之后的推理階段就可省去BN 層的計算[8]。
考慮到MobileNetv2 結構的重復性,將整個網絡分成三個部分來設計:Bottleneck 部分、Bottleneck 之前以及之后的部分。在每個部分也有基礎的計算單元,如普通二維卷積、深度卷積、逐點卷積、殘差結構以及全劇平均池化層等,本文將這些基礎單元單獨設計成IP計算核。
加速器總的系統結構塊設計如圖4 所示,左邊是HLS 設計導出的5 個IP 核,中間從上往下分別是ZYNQ 的中心處理模塊和時鐘與復位信號模塊,右邊的兩列則是傳輸總線AXI 的相關模塊,對塊設計進行綜合之后得到總的資源使用情況,如圖5所示。

圖4 加速器整體塊設計

圖5 綜合資源占用情況
1.3.1 pingpong操作
在兩個計算模塊之間傳遞數據時,由于前一個模塊需要等待下一個模塊計算完成才能交付數據,造成了一定的性能損失,所謂ping?pong 操作是指設置緩沖來進行交替存儲,進而實現讀、算、寫的同步。
數據的分塊計算使得多個模塊之間的計算滿足上述情況,所以設置兩個buffer來實現數據的pingpong 操作,buffer 的大小根據不同IP 核進行獨立設置。pingpong操作的計算原理如圖6所示。

圖6 pingpong操作原理
1.3.2 for循環展開
HLS 可以使用Unroll 指令對for 循環進行展開,for 循環在默認狀態下是折疊狀態的,即在電路里中每一次循環都會分時地使用同一套電路。使用Unroll 可以對for 循環的代碼區進行循環體展開,將之前的電路復制多份,實現以資源換取并行的計算邏輯,如圖7 所示。Unroll 允許完全展開或部分展開,其中部分展開需要指定循環因子factor=N,即把循環展開N倍來減少循環迭代。

圖7 Unroll循環展開原理
1.3.3 多精度計算優化
在IP核中采用的是AP_FIX16的精度進行存儲和運算,這就有可能會因為數據精度過低以及數值溢出而產生一些計算誤差,并有可能在深度神經網絡中持續積累這種誤差。于是本文在考慮資源占用的同時,采用多精度數據的方式來避免這種精度的溢出:將輸入與輸出設置為AP_FIX16的數據類型,然后在計算卷積的過程中,擴大精度來保存臨時的數值,并在最后輸出時恢復為最開始的精度。
1.3.4 計算分組分塊
由于網絡模型的參數量比較大,直接使用FPGA 中片上資源來保存每一層所有的數據并不是一個好的方法,所以本文對網絡的各個模塊用數據分組分塊的方式來計算,以降低片內資源的占用,并配合pingpong 操作等優化方式進行并行計算,其過程如圖8所示。

圖8 分組分塊計算
1.3.5 流水線優化
流水線的設計思想是新的輸入數據在前面的數據計算完成之前就能提前處理,例如有一個復雜電路,它需要固定的時間周期才能得出最后的穩定結果,我們將其拆解為N個步驟,第一個步驟計算完成后將結果存起來傳送給第二個步驟,然后緊接著繼續往第一個步驟輸入數據,以此類推,用這種方式實現流水線優化的并行處理,如圖9所示。

圖9 流水線加速時序
1.3.6 加法器樹優化
在一次卷積計算過程中涉及到多次加法的運算,這個時候可以采用加法器樹的設計方式,將卷積運算單元中的相加過程設計為樹形的并行相加模式,進而提高運算效率,可以把時鐘周期為N的工作縮小到log2N個時鐘周期。
通過實驗對比,在不使用并行加速策略時,單核的Arm 設備平均耗時為35.6 s,而本文使用上述的并行優化設計,在KV260 的ZYNQ 平臺中的平均計算耗時降低到0.046 s,且功耗并無明顯變化,證明該加速器在保證功耗基本不變的情況下,還能充分發揮FPGA 的并行計算優勢,提高計算速度。

表2 加速器優化策略性能對比
該部分是神經網絡最上層卷積,輸入為224×224×3 的圖像數據與該層的權重數據。為了提升計算速度,我們對數據流進行了控制,將輸入分為三個通道來處理輸入數據,使用三條128位AXI總線進行傳輸。在實際傳輸時數據為16 位的定點數,這里將24 個16 位定點數打包,同時在AXI 總線上進行并行傳輸。對于權重、偏置和輸出則分別使用一條64 位AXI 總線進行傳輸。
為進一步提升計算效率,對計算分為兩路的pingpong 緩存和計算,如圖10 所示。在ping?pong 操作中進行后續的循環展開計算卷積模塊,將輸入數據進行如圖8的分塊卷積操作,對于權重來說,同樣在for循環中每次讀取出8個filter來進行卷積操作,以達到數據并行計算的目的。

圖10 pingpong模塊偽代碼
經過HLS 仿真測試和綜合之后,得到其資源使用報告,如圖11所示。

圖11 普通二維卷積IP核綜合報告
Depthwise 是逐通道卷積,是將特征圖的每個通道單獨使用卷積核來進行卷積操作,獲得特征圖每個通道的空間特征,并使得到的特征圖和輸入的通道數保持一致。逐通道卷積的卷積計算采用PIPELINE 指令進行流水優化以及UNROLL 進行循環展開,同時利用pingpong 模塊對緩存和計算進行并行處理。在接口方面,將輸入設置為兩個不同通道來處理輸入數據,使用兩條64 位AXI 總線進行傳輸,同樣將8 個16 位定點數據打包到AXI 總線上并行傳輸,權重和偏置則采用一條32位AXI總線進行傳輸。
由于每次不同層的逐通道卷積尺寸不同,我們將數據分塊來實現統一的單元化卷積計算,具體是將數據切分為若干個8×32 的小尺寸,且進一步將32 劃分為4×8 的多通道數據,使得不同尺寸的卷積轉換為多個固定尺寸的小的卷積,有利用逐通道卷積的加速核的統一化設計。對于不同步長的層,可通過傳入的stride 值判斷輸出特征尺寸是否需要減半。分塊卷積的偽代碼如圖12 所示,W為卷積核的大小,B_r、B_c、B_ch 分別為分塊的尺寸以及通道大小,在B_ch處進行PIPELINE 循環展開,使用B_ch 個并行的乘法器和深度為[log2B_ch]的加法器樹,每時鐘將輸入緩存的ch 個通道的特征值與對應的權重值進行乘法計算,然后將計算的數據進行累加,并使用加法器樹優化計算,最后通過輸出緩存存儲結果。

圖12 分塊卷積實現偽代碼
在HLS 中進行仿真和綜合后的報告如圖13所示。

圖13 逐通道卷積層IP核綜合報告
Pointwise 是逐點卷積,使用和輸入特征圖通道相同數量的1*1 的卷積核,對特征圖深度方面做了加權組合,相當于獲得每個點的特征信息,大大減小了總體的計算量。
在具體的實現中,使用兩條64 位AXI 總線進行傳輸,同樣將8 個16 位定點數據打包到AXI 總線上并行傳輸,權重和偏置則分別采用兩條64 位AXI 總線和用一條32 位AXI 總線進行傳輸。計算部分由于該模塊存在許多1*1 的卷積,計算得到的通道數相對較多,同樣采用了數據分塊的思想,利用兩層pingpong 嵌套操作來讀取權重和特征數據并進行卷積計算。
同樣經過仿真以及HLS 綜合之后獲得資源使用情況的報告,如圖14所示。

圖14 逐點卷積層IP核綜合報告
由于已經單獨實現了逐通道卷積和逐點卷積,所以這里殘差層是指最后的原始數據與經過了殘差之后的輸出相加的操作,并通過流水展開來進行加速。
全連接模塊由全局平均池化層和全連接層組成,本文將其實現為一個IP 核,輸入大小為7×7×Channel,輸出為最后的分類結果。接口方面直接使用一條16 位AXI 總線進行傳輸,具體的實現則是將卷積核的值當做分數來模擬求平均的計算,使用加法器樹對齊進行并行加速,加載數據時同樣利用pingpong 模塊來進行緩存和計算優化。仿真和綜合之后得到報告,如圖15所示。

圖15 殘差層、全連接層IP核綜合報告
經過上述的仿真和綜合之后,從Vivado HLS 2020.2 中導出IP 核的壓縮文件,在Vivado 2020.2 中導入IP 文件并在塊設計中進行連線。對塊設計進行仿真和綜合后得到.bit 和.hwh 文件,利用Python 語言調用PYNQ 軟件層的接口進行主機端編程。
數據集采用公開的DeepFashion 服裝數據集來進行訓練和測試,其中包括運動夾克、毛衣、連衣裙等46種類別,并使用2000張測試圖片進行上板驗證。分別從計算時間、識別準確率、芯片功耗幾個方面來展示在KV260 的FPGA 上推理MobileNetv2 網絡的實驗結果,并且將該結果分別與網絡在CPU 和GPU 計算平臺上的推理結果作為對比來分析基于FPGA方法的優勢。
對于使用FPGA 加速器的方案,使用賽靈思的Kria KV260 作為硬件計算平臺;對于直接使用CPU 的方案,使用i7-12th 作為硬件計算平臺;而對于使用GPU 的方案,則使用RTX3060作為硬件計算平臺。

表3 計算速度對比
本文基于賽靈思提供的Kria KV260開發板,使用高層次綜合工具通過C++語言進行Mobile?Netv2 的加速核設計,并在使用Python 在PYNQ平臺中對主機端進行編程以及驗證推理。實驗表明,相比單核的Arm芯片,利用FPGA的并行計算設計以及HLS 相關指令對加速核進行計算優化效果明顯,且該種方法設計的卷積神經網絡加速器在推理Top1 上并無明顯下降,在計算速度上相較于CPU 來說提升了2 倍左右,雖然與GPU 相比還是有一定差距,但在功耗方面降低了10倍左右,有著較大的優勢。