許 杰,張子恒,王新宇,佟 誠,梅 青,肖 建
(南京郵電大學(xué) 電子與光學(xué)工程學(xué)院、微電子學(xué)院,江蘇 南京 210023)
卷積神經(jīng)網(wǎng)絡(luò)(convolutional neural network,CNN)廣泛應(yīng)用在圖像識別[1]、目標(biāo)檢測[2]等領(lǐng)域。CNN所需的計算量和數(shù)據(jù)量巨大,單核數(shù)量和訪存帶寬有限的中央處理器(central processing unit,CPU)不能滿足其吞吐量和存儲量的設(shè)計要求,研究人員將CNN加速器的實現(xiàn)主要集中在圖形處理器(graphics processing unit,GPU)、專用集成電路[3-4](application specific integrated circuit,ASIC)芯片和現(xiàn)場可編程邏輯門陣列[5-8](field programmable gate array,F(xiàn)PGA)等三類器件上。
GPU可以提供較高的并行度、矩陣計算和浮點(diǎn)運(yùn)算能力,但巨大的功耗消耗使其難以應(yīng)用在功耗與面積受限的應(yīng)用平臺。ASIC能夠在特定功能上進(jìn)行強(qiáng)化,具有更高的處理速度和更低的能耗。但是研發(fā)成本高,前期研發(fā)投入周期長、靈活性較差。FPGA比特級細(xì)粒度定制的結(jié)構(gòu)、流水線并行計算的能力和高效的能耗,使得其在CNN加速器的研究中具有極大的優(yōu)勢。
同時,F(xiàn)PGA是半定制的硬件,通過編程可重定義其內(nèi)部配置和鏈接,具有較大的靈活性。
近年來,越來越多的CNN加速器設(shè)計被提出。Zhang等人[9]提出了一種基于roofline模型在FPGA上的加速卷積神經(jīng)網(wǎng)絡(luò)。Qiu等人[10]提出了一種FPGA設(shè)計來加速嵌入式系統(tǒng)上的大規(guī)模圖像分類挑戰(zhàn)的CNN。蘇黎世聯(lián)邦理工學(xué)院團(tuán)隊基于SqueezeNet[11]模型訓(xùn)練出了適合在FPGA上運(yùn)行的ZynqNet網(wǎng)絡(luò),并針對網(wǎng)絡(luò)實現(xiàn)了FPGA硬件加速[12]。Li等人[13]提出了一種端到端的基于FPGA的CNN加速器,將所有的層都映射到片上,各層之間流水化實現(xiàn),但只適合資源較多的FPGA。
文中先對Caffe[14]神經(jīng)網(wǎng)絡(luò)框架范例中的cifar10_quick[15]網(wǎng)絡(luò)做微小的調(diào)整,然后設(shè)計相應(yīng)的硬件加速器,并對每層的硬件加速策略做詳細(xì)的闡述。最后,在Xilinx的Zynq7020實驗平臺上進(jìn)行評估。
CIFAR-10[16]數(shù)據(jù)集由10類32×32的彩色圖片組成,一共包含60 000張圖片,每一類包含6 000圖片。其中50 000張圖片作為訓(xùn)練集,10 000張圖片作為測試集。
cifar10_quick模型出自Caffe神經(jīng)網(wǎng)絡(luò)框架中關(guān)于CIFAR-10數(shù)據(jù)集的樣例,由3層卷積層、3層池化層和2層全連接層構(gòu)成,輸入32×32×3的圖像數(shù)據(jù),輸出10類物體分類的結(jié)果。選擇其中數(shù)值最大的結(jié)果輸出,即為最終分類的結(jié)果。cifar10_quick模型3個池化層對應(yīng)的步長為2,池化窗口的大小為3×3,訓(xùn)練5 000個批次,達(dá)到的準(zhǔn)確率為75%左右。文中保持3個池化層的步長為2不變,池化濾波器的大小修改為2×2,訓(xùn)練后準(zhǔn)確率達(dá)到80%。圖1中展示了修改后cifar10_quick_v1模型的網(wǎng)絡(luò)結(jié)構(gòu)。

圖1 cifar10_quick_v1網(wǎng)絡(luò)結(jié)構(gòu)
CNN模型訓(xùn)練完畢后,可以提取相應(yīng)的權(quán)重和偏置。采用GPU進(jìn)行訓(xùn)練,默認(rèn)保存數(shù)據(jù)的類型為雙精度浮點(diǎn)數(shù),每一個數(shù)據(jù)占用64 bit的位寬。在FPGA中,邏輯資源有限,故使用定點(diǎn)數(shù)表示相應(yīng)的權(quán)重、偏置以及輸入特征及輸出特征。
首先,分析網(wǎng)絡(luò)參數(shù)的范圍,確定最終的量化位數(shù),保證量化的數(shù)據(jù)不會比原有數(shù)據(jù)失真太多。然后,確定浮點(diǎn)數(shù)包含的位數(shù),即量化精度,量化后的整數(shù)范圍不能比原有數(shù)據(jù)小,同時盡可能地提升浮點(diǎn)數(shù)所能表示的精度。值得注意的是,最高位為符號位,量化的定點(diǎn)數(shù)要支持負(fù)數(shù)。所有數(shù)據(jù)的量化需滿足下列的公式(1)[17]:
2W-P-1>max(|Dmax|×2P,|Dmin|×2P) (1)
其中,P為量化精度,W為量化位寬,D表示量化前的浮點(diǎn)數(shù)據(jù)。
文中采用16位定點(diǎn)數(shù)進(jìn)行存儲,相比于GPU的64 bit的雙精度浮點(diǎn)數(shù),可以減少3/4的存儲量。浮點(diǎn)數(shù)轉(zhuǎn)換為定點(diǎn)數(shù)極大地節(jié)省了邏輯資源,相較于浮點(diǎn)運(yùn)算,定點(diǎn)運(yùn)算在速度上具有明顯優(yōu)勢。
一個卷積神經(jīng)網(wǎng)絡(luò)由卷積層、池化層、全連接層以及非線性函數(shù)等四部分組成,還可能包括局部響應(yīng)歸一化[18](local response normalization,LRN)層和批歸一化[19](batch normalization,BN)層,以及Dropout[20]層等。而卷積層占據(jù)了90%的計算量[21],全連接層占據(jù)了大量的參數(shù)量,故將重點(diǎn)放在卷積層和全連接層的優(yōu)化上,池化層作為整個卷積神經(jīng)網(wǎng)絡(luò)的一部分,亦在優(yōu)化范圍內(nèi)。
cifar10_quick_v1模型是在Zynq芯片中實現(xiàn)的,而Zynq芯片主要由兩部分組成:雙核ARM Cortex-A9構(gòu)成的處理系統(tǒng)(processing system,PS)和等價于一片 FPGA的可編程邏輯(programmable logic,PL)。值得注意的是,Zynq7020芯片屬于Zynq-7000系列的低端產(chǎn)品,F(xiàn)PGA邏輯資源有限,不適合將整個卷積神經(jīng)網(wǎng)絡(luò)映射到Zynq的PL端進(jìn)行加速[13]。
如何充分利用Zynq的PS端的雙核處理器系統(tǒng)與PL端的FPGA邏輯進(jìn)行協(xié)同設(shè)計,就顯得非常重要。FPGA工作頻率雖然不高,卻有著極大的并行化處理優(yōu)勢,將加速的部分部署在PL端,能夠很大程度上加速卷積神經(jīng)網(wǎng)絡(luò)的運(yùn)行。PS端工作頻率高,與PL端高度的并行化處理相比,在計算上卻沒有明顯的優(yōu)勢,其優(yōu)勢在于強(qiáng)大的管理和調(diào)度能力。
軟硬件協(xié)同設(shè)計框架如圖2所示。卷積神經(jīng)網(wǎng)絡(luò)的權(quán)重和偏置及輸入特征存儲在外部存儲器DDR3中,加速時Zynq的PS端將各層的權(quán)重和偏置以及輸入特征由DDR3加載給PL端,PL端進(jìn)行各層的硬件加速,計算完畢后,再將各層運(yùn)算的結(jié)果輸出到DDR3。按照先后順序,直到最后一層計算完畢,輸出最終的運(yùn)算結(jié)果。

圖2 軟硬件協(xié)同設(shè)計框架
由此可知,整個卷積神經(jīng)網(wǎng)絡(luò)的優(yōu)化涉及兩個方面,一是各層之間數(shù)據(jù)傳輸優(yōu)化,減少數(shù)據(jù)傳輸?shù)臅r間,二是各層內(nèi)部計算的優(yōu)化,主要是優(yōu)化計算速度,減少PL端和DDR3內(nèi)存之間的數(shù)據(jù)交互。
池化(也稱為子采樣)用于減少特征圖的空間尺寸,從而在網(wǎng)絡(luò)中減少參數(shù)和計算量。定期插入池化層在連續(xù)的卷積層之間,其獨(dú)立于每一個輸入的深度切片,并在特征圖上求最大值調(diào)整輸入特征的大小。最常見的形式是過濾器大小為2×2的池化層,每一次濾波器的移動最多可獲取4個樣本從而丟棄了75%的輸入數(shù)據(jù)。除了常用的最大池化外,一些CNN也用于執(zhí)行其他功能,例如平均池化和最小池化等[22]。
若無優(yōu)化,池化層的實現(xiàn),不論是取數(shù)據(jù)的過程,還是計算的過程,都是順序執(zhí)行。而FPGA邏輯資源有限,故只采用流水線的方式加速池化層的運(yùn)行。
關(guān)于流水線的優(yōu)化方式,以最大池化為例,池化層的濾波器大小為2×2,需選取濾波器對應(yīng)的4個數(shù)據(jù)中最大的數(shù)據(jù)。具體地,先取濾波器中的兩個數(shù)據(jù),選取較大的數(shù)據(jù),暫存為tmp_max1,再取剩余的兩個數(shù)據(jù),選取較大的數(shù)據(jù),暫存為tmp_max2,tmp_max1和tmp_max2進(jìn)行比較,較大的數(shù)據(jù)即為最終的結(jié)果。從兩個數(shù)據(jù)的讀取、比較到臨時結(jié)果的暫存,是一個連續(xù)的過程。若未采用流水線,剩余的兩個數(shù)據(jù)的運(yùn)算過程,必須等待前兩個數(shù)據(jù)的運(yùn)算全部執(zhí)行完畢后,才能開始執(zhí)行。若采用流水線,前兩個數(shù)據(jù)的讀取完畢后,緊接著就是后兩個數(shù)據(jù)的讀取過程,同時前兩個數(shù)據(jù)進(jìn)行比較。下一個時鐘周期,后兩個數(shù)據(jù)的比較與前兩個比較結(jié)果的暫存同步執(zhí)行。直到算出最終的結(jié)果,后兩個數(shù)據(jù)的運(yùn)算過程與前兩個數(shù)據(jù)的運(yùn)算過程相比,只有一個時鐘周期的間隔,極大地增加了運(yùn)算速度。
池化層內(nèi)部的計算采用流水線的方式實現(xiàn),池化層與全連接層之間的數(shù)據(jù)傳輸,也需要優(yōu)化。若池化層單獨(dú)進(jìn)行優(yōu)化,則卷積層計算完畢后,將輸出特征暫存到DDR3,池化層再將該輸出特征加載到Zynq的PL端,池化層優(yōu)化計算后,輸出結(jié)果到DDR3。運(yùn)算過程中沒有很復(fù)雜的運(yùn)算,卻增加了數(shù)據(jù)存取過程,花費(fèi)了大量的時間。若卷積層和池化層合并,即卷積層運(yùn)算的結(jié)果直接傳輸?shù)匠鼗瘜訁⑴c運(yùn)算,減少DDR3與PL端的數(shù)據(jù)交互,速度上會有很大的提升,如圖3所示。

圖3 池化層緩存優(yōu)化示意圖
卷積層的計算如圖4所示。卷積層接收CHin個特征圖作為輸入,每個輸入特征圖由一個帶有K×K大小的核的移動窗口卷積以在一個輸出特征圖中生成一個像素。移位窗口的步幅為S(通常為1,小于K),總共CHout個輸出特征圖將形成下一個卷積層的輸入特征圖集[9]。

圖4 卷積層計算框圖
卷積層的計算可用公式(2)表示:
Out[cho][r][c] =

In[chi][r+kr][c+kc]
(2)
其中,Out是輸出特征變量,W是輸入權(quán)重變量,In是輸入特征變量,Row是輸出特征對應(yīng)的行數(shù),Col是輸出特征對應(yīng)的列數(shù), chi是輸入通道數(shù)CHin對應(yīng)的變量,cho為輸出通道數(shù)CHout對應(yīng)的變量,kr和kc分別是權(quán)重濾波器的行數(shù)或列數(shù)K對應(yīng)的變量,r是輸出特征的行數(shù)Row對應(yīng)的變量,c是輸出特征的列數(shù)Col對應(yīng)的變量。
2.3.1 整體框架
卷積層優(yōu)化的整體框架如圖5所示。每一層卷積層的計算,都是Zynq的PS端將DDR存儲的輸入特征、權(quán)重以及偏置加載到PL端,PL端加速卷積層的運(yùn)算,計算的結(jié)果作為池化層的輸入特征,池化層計算完畢后,再將最終的結(jié)果輸出到DDR3中暫存。池化層從4個數(shù)據(jù)中提取出一個數(shù)據(jù),故從卷積層的計算結(jié)果,到池化層的輸出特征,可以節(jié)省3/4的內(nèi)存空間,同時減少DDR3和PL端數(shù)據(jù)交互的時間。

圖5 卷積層優(yōu)化整體框圖
2.3.2 卷積層輸入輸出通道分塊策略
卷積層的計算量是最大的,充分利用FPGA并行化處理的優(yōu)勢能夠加速卷積的運(yùn)算。FPGA的邏輯資源有限,僅將輸入輸出通道分塊處理,同時分塊后的輸入輸出通道的卷積計算并行化實現(xiàn)。
輸入輸出通道分塊,則分塊后的每次卷積運(yùn)算不需要所有的權(quán)重、偏置以及輸入特征參與。所有的輸入數(shù)據(jù)可以按照輸入輸出通道分塊,根據(jù)分塊的大小加載部分的權(quán)重、偏置以及輸入特征到Zynq的PL端。另一方面,若權(quán)重和偏置以及輸入特征,完全按照輸入輸出通道分塊,分塊后各個分塊大小所包含的數(shù)據(jù)量可能非常小,就會增加DDR3和PL端的數(shù)據(jù)交互次數(shù),極大地增加FPGA訪問外部存儲器的時間。
因此,從DDR3加載權(quán)重、偏置以及輸入特征時,僅按照輸入通道分塊讀取。如圖6所示,輸入通道數(shù)用CHin表示,以ITILE作為輸入通道分塊的基數(shù),則輸入通道分塊的大小n為CHin/ITILE。首先,輸入偏置的數(shù)據(jù)量與輸出通道數(shù)一致,一次性將所有的輸入偏置加載到Zynq的PL端;其次,輸入特征按照輸入通道分塊,分步加載輸入特征;最后,輸入權(quán)重僅按照輸入通道分塊,所有輸出通道對應(yīng)的權(quán)重都一次性加載到PL端。也即每次加載到PL端的輸入數(shù)據(jù)只有輸入通道上不完整,將當(dāng)前輸入通道分塊的所有輸出通道的卷積計算(在Conv函數(shù)中實現(xiàn))完畢后,再加載下一個輸入通道分塊的數(shù)據(jù),直到所有的輸入通道的數(shù)據(jù)加載并計算完畢,將所有輸入通道分塊卷積計算的結(jié)果累加,就可以獲得最終的卷積運(yùn)算的結(jié)果。一層卷積層的卷積運(yùn)算完畢后,才將最終的輸出特征傳輸?shù)紻DR3,亦減少了FPGA和外部存儲器的數(shù)據(jù)交互時間。

圖6 卷積層加載輸入數(shù)據(jù)示意圖
2.3.3 卷積層輸入權(quán)重重組
為了保證輸入權(quán)重從DDR3加載到Zynq的PL端的地址變化的連續(xù)性,減少DDR3地址的跳變,引入權(quán)重重組的策略,實施過程如圖7所示。默認(rèn)情況下,權(quán)重的加載過程是先按照第一個輸出通道對應(yīng)的輸入通道加載數(shù)據(jù),該輸出通道對應(yīng)的所有輸入通道的權(quán)重加載完畢后,切換下一個輸出通道的權(quán)重,直到所有輸出通道的權(quán)重加載完畢。然而,文中僅按照輸入通道分塊加載權(quán)重,先計算部分輸入通道對應(yīng)的所有輸出通道卷積運(yùn)算的結(jié)果,故DDR3地址的變化過程必然不是連續(xù)的。為了減少DDR3地址的跳變,權(quán)重進(jìn)行重新排序,即先將所有輸出通道對應(yīng)ITILE個輸入通道的權(quán)重加載到PL端,然后加載下一部分所有輸出通道對應(yīng)的ITILE個輸入通道的權(quán)重,直到所有的輸入輸出通道的權(quán)重加載完畢。

圖7 卷積層權(quán)重重組示意圖
2.3.4 卷積層輸入輸出通道分塊并行化
輸出通道分塊僅體現(xiàn)在卷積的計算上,輸出通道數(shù)為CHout,以O(shè)TILE作為輸出通道分塊的基數(shù),則輸出通道分塊的大小m為CHout/OTILE。不同輸出通道的卷積計算完全是獨(dú)立的,計算所需的權(quán)重在不同輸出通道完全是不同的,將不同輸出通道分塊的卷積計算完畢即可,無需將不同輸出通道的結(jié)果進(jìn)行累加。
輸入輸出通道分塊后的計算如圖8所示。分塊后,共有ITILE個輸入通道,OTILE個輸出通道,ITILE個輸入特征和ITILE個權(quán)重乘積運(yùn)算并行,再將ITILE個乘積運(yùn)算的結(jié)果累加,該過程對于OTILE個輸出通道是完全并行的。對于每一個輸出點(diǎn)的ITILE個輸入通道,每一個輸入通道權(quán)重濾波器內(nèi)K*K個元素與輸入特征一一對應(yīng)。將不同輸入通道的權(quán)重濾波器內(nèi)元素與對應(yīng)輸入特征元素的乘積累加(采用流水線的優(yōu)化方式),就可以獲得一個輸出點(diǎn)的運(yùn)算結(jié)果,最終會有OTILE*Row*Col個結(jié)果輸出。

圖8 卷積層分塊并行化示意圖
全連接層的計算比卷積層的計算簡單,只需將一個輸出通道的不同輸入通道的權(quán)重與對應(yīng)的輸入特征相乘,得到的所有乘積累加,再加上對應(yīng)輸出通道的偏置,就能得到該輸出通道的結(jié)果。
全連接層的計算用公式(3)表示:

(3)
其中,Out是輸出特征變量,W是輸入權(quán)重變量,In是輸入特征變量,F(xiàn)Cin是輸入通道數(shù),fci是輸入通道數(shù)FCin對應(yīng)的變量,fco是輸出通道數(shù)對應(yīng)的變量。
2.4.1 全連接層輸出通道分塊策略
全連接層的不同輸出通道的計算所需的權(quán)重不同,輸入特征卻完全相同,即不同輸出通道全連接層的計算是相互獨(dú)立的,可以并行化實現(xiàn)。然而,所有輸出通道的并行化計算,所需的FPGA邏輯資源是巨大的,故借鑒卷積層的分塊策略,每次只計算部分輸出通道的結(jié)果。
將DDR3存儲的全連接層對應(yīng)的輸入特征,一次性全部加載到PL端。輸入偏置亦是如此,不過加載到PL端后,按照輸出通道分塊進(jìn)行重組。輸入權(quán)重則不同,按照輸出通道分塊進(jìn)行數(shù)據(jù)的加載,每次只加載部分輸出通道的數(shù)據(jù)。計算完一個輸出通道分塊后,再加載下一個輸出通道分塊的權(quán)重,直到所有的輸出通道計算完畢。每一個輸出通道的全連接層的計算是相互獨(dú)立的,故每個輸出通道分塊的計算(在FC函數(shù)中實現(xiàn))也是相互獨(dú)立的,所有輸出通道分塊計算完畢后,整合所有輸出通道的結(jié)果,再將最終的輸出特征輸出到DDR3,亦減少了FPGA與DDR3的數(shù)據(jù)交互時間,如圖9所示。

圖9 全連接層加載輸入數(shù)據(jù)示意圖
2.4.2 全連接層輸出通道分塊并行化
全連接層輸出通道分塊的并行化實現(xiàn)和卷積層輸入輸出通道分塊的并行化實現(xiàn)類似,區(qū)別在于并行化的FTILE個輸出通道中,只有一個輸入通道的輸入特征和權(quán)重的乘積運(yùn)算是并行化實現(xiàn)的,各輸入通道之間運(yùn)算的切換采用流水線的優(yōu)化方式。即FTILE個輸出通道中,第一個輸入通道的乘積運(yùn)算計算完畢后,接著下一個輸入通道進(jìn)行乘積運(yùn)算,直到所有的輸入通道計算完畢。將所有輸入通道的結(jié)果相加,總共有FTILE個輸出結(jié)果,對應(yīng)于FTILE個輸出通道。全連接層的輸出通道數(shù)用FCout表示,則輸出通道分塊的大小為FCout/FTILE。
前文分別對卷積層、池化層、全連接層進(jìn)行了優(yōu)化,整個卷積神經(jīng)網(wǎng)絡(luò)優(yōu)化完畢。
本設(shè)計在Xilinx Zynq7020平臺中進(jìn)行驗證,雙核Cortex-A9的PS端和Zynq的PL端都工作在100 MHz的頻率下。Zynq的PS端從SD卡中讀取CIFAR-10數(shù)據(jù)集的測試集作為測試數(shù)據(jù),10 000張圖片分張進(jìn)行測試,CNN加速器在不同的OTILE、ITILE和FTILE的參數(shù)條件下進(jìn)行測試。
共4組參數(shù)進(jìn)行實驗對比。軟件優(yōu)化時,使用單核Cortex-A9進(jìn)行測試,其他組采用不同OTILE、ITILE和FTILE的參數(shù)配置進(jìn)行對比。記錄各層優(yōu)化后的平均計算時間和加速比,生成的表格如表1所示。

表1 不同參數(shù)配置下性能對比
不同OTILE、ITILE和FTILE的參數(shù)配置進(jìn)行硬件優(yōu)化,會有不同的資源占用情況與之對應(yīng),制成的表格如表2所示。

表2 不同參數(shù)配置下資源占用情況對比 %
在Zynq7020實驗平臺中對cifar10_quick_v1整個CNN模型進(jìn)行設(shè)計,通過對卷積層輸入輸出通道分塊及并行化設(shè)計,對池化層流水線優(yōu)化,以及全連接層輸出通道分塊及并行化設(shè)計,充分利用FPGA的并行化優(yōu)勢,同時減少FPGA與DDR3的數(shù)據(jù)交互。最終,相比于單核Cortex-A9實現(xiàn)整個網(wǎng)絡(luò)結(jié)構(gòu),采用OTILE=8,ITILE=4,F(xiàn)TILE=4的參數(shù)優(yōu)化的網(wǎng)絡(luò)可以達(dá)到144倍的加速,亦占用了Zynq的PL端大部分的邏輯資源。