鄧 良,陳章進,2,喬 棟,屠程力
1(上海大學(xué) 微電子研究與開發(fā)中心,上海 200444)2(上海大學(xué) 計算中心,上海 200444)
E-mail:1593481663@qq.com
隨著近年來大數(shù)據(jù)的爆發(fā)與計算機性能的飛躍式的提升,人工智能的研究重新變得火熱起來,神經(jīng)網(wǎng)絡(luò)算法已經(jīng)被廣泛應(yīng)用于圖像處理[1]、人臉識別[2]、語音識別[3]等場景.隨著神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)的不斷加深,對運算平臺的資源與計算能力要求越來越高,使得通用處理器對于網(wǎng)絡(luò)模型的運算越來越吃力.目前針對神經(jīng)網(wǎng)絡(luò)模型進行加速的方案主要有3種:1)使用圖像處理器GPU進行模型計算的加速,但存在著功耗高,難于集成等缺點,只適合于大型運算平臺或云端服務(wù)器;2)使用專用集成電路進行模型計算的加速,具有更高性能、更低功耗的特點,但存在設(shè)計周期長、開發(fā)成本高等缺點;3)使用FPGA進行模型計算的加速,具有低功耗、開發(fā)周期短、靈活性高等特點[4],逐漸成為目前研究神經(jīng)網(wǎng)絡(luò)加速的熱門平臺.
2011年Farabet等[5]人提出了一種基于FPGA的卷積神經(jīng)網(wǎng)絡(luò)處理器,該處理器在計算時可重構(gòu)數(shù)據(jù)流,包含了多個計算單元.2013年P(guān)eenmen M等[6]人在Virtex6 FPGA上實現(xiàn)了卷積神經(jīng)網(wǎng)絡(luò)的加速,使用MicroBlaze軟核處理器作為控制器.2014年Gokhale V等[7]人使用Xilinx ZYNQ FPGA設(shè)計了一種卷積神經(jīng)網(wǎng)絡(luò)加速器,該方法使用8路并行的計算單元,每個計算單元能夠進行最大10×10的卷積計算.2016年Motamedi M等[8]人提出了輸出間并行、卷積核間并行和卷積核內(nèi)并行3種可行的并行計算方法,詳盡的總結(jié)了卷積層并行計算的設(shè)計方案.2017年Yu 等[9]人使用Winograd算法[10]實現(xiàn)卷積運算,減少了模型計算過程中乘法器的使用數(shù)量,提高了計算的并行度,但Winograd算法通常只適用于較小的卷積神經(jīng)網(wǎng)絡(luò)模型.2019年曾成龍等[11]人提出了一種單計算引擎的神經(jīng)網(wǎng)絡(luò)加速器的設(shè)計方案,只使用單個計算引擎進行實時配置實現(xiàn)不同卷積神經(jīng)網(wǎng)絡(luò)層的計算,大大減小對FPGA資源的消耗.
這些研究工作主要關(guān)注于對并行設(shè)計空間的探索,嘗試通過使用多計算單元計算,數(shù)據(jù)分塊與并行,使用流水計算等方法提高設(shè)計的并行度,往往需要消耗大量的資源,而沒有全面考慮到對FPGA資源的合理利用,基于FPGA的神經(jīng)網(wǎng)絡(luò)加速架構(gòu)主要有數(shù)據(jù)流處理架構(gòu)和單計算單元架構(gòu)2種[12].數(shù)據(jù)流處理架構(gòu)通常是在FPGA上實現(xiàn)神經(jīng)網(wǎng)絡(luò)模型的全部層,數(shù)據(jù)從實現(xiàn)這些層的電路中流過就完成了一次計算,因為每一層的電路結(jié)構(gòu)都經(jīng)過精心的設(shè)計,能夠為每一層靈活的配置資源,提高計算的性能.但是當(dāng)計算不同的神經(jīng)網(wǎng)絡(luò)模型時,需要重新配置FPGA,并且這種方法對FPGA設(shè)備的資源要求很高,對于大型的神經(jīng)網(wǎng)絡(luò)模型,很難進行部署.單計算單元架構(gòu)的加速器通過對計算單元的配置來實現(xiàn)神經(jīng)網(wǎng)絡(luò)中不同層的計算,按照一定的配置順序就能實現(xiàn)整個神經(jīng)網(wǎng)絡(luò)的計算,當(dāng)計算不同的神經(jīng)網(wǎng)絡(luò)模型時,只需要改變配置順序即可,與數(shù)據(jù)流處理架構(gòu)相比,盡管達不到最佳的計算性能,但占用資源少,靈活性與通用性強.
本文基于FPGA平臺提出一種自定義指令集的神經(jīng)網(wǎng)絡(luò)處理器的設(shè)計方案,指令集包含了16條的運算指令,該處理器使用128位寬的指令來控制實現(xiàn)不同計算操作,對卷積與池化系列的計算電路進行復(fù)用,減少對FPGA資源的消耗,使用流水線CORDIC算法[13]實現(xiàn)激活函數(shù)的計算,同時本文設(shè)計了一種多端口讀寫控制模塊,處理器通過該模塊實現(xiàn)對總線數(shù)據(jù)的讀寫.
卷積神經(jīng)網(wǎng)絡(luò)[14]是神經(jīng)網(wǎng)絡(luò)中最常用到的網(wǎng)絡(luò)之一,卷積神經(jīng)網(wǎng)絡(luò)模型通常包括:卷積層、池化層、激活函數(shù)計算、全連接層等.卷積神經(jīng)網(wǎng)絡(luò)每一層的輸入通常都是一個三維矩陣,分別定義為:長、寬、深度,深度有時也被表述為通道數(shù).圖1是一種常見的卷積神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu).
圖1 卷積神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)圖Fig.1 Convolutional neural network structure
2.1.1 卷積層運算模型
卷積層的作用是為了提取輸入圖像的某些特征,并輸出一個新的特征圖作為下一層的輸入圖像,計算的過程通常為先卷積再經(jīng)過一個激活函數(shù)得到結(jié)果.卷積層存在4種卷積的實現(xiàn)方式:直接卷積、展開式卷積[15]、Winograd卷積和快速傅里葉卷積[16].本文中使用直接卷積的方法進行計算.直接卷積使用卷積核與在圖像上截取到的相同尺寸的圖像進行累乘和累加計算,計算的數(shù)學(xué)表達式為:
(1)
其中f(·)是非線性激活函數(shù),βfi表示偏移值,O(x,y)表示輸入特征圖坐標(biāo)(x,y)處的值,w(kx,ky)表示卷積核坐標(biāo)(kx,ky)上的權(quán)重值,In(x+kx,y+ky)表示輸出特征圖坐標(biāo)(x+kx,y+ky)上的值;kx,ky表示卷積核的大小,fi表示第i幅輸入特征圖,Nfi表示輸入特征圖的數(shù)目.
2.1.2 池化層運算模型
池化層也被稱為下采樣層,通常被放置在卷積層后,根據(jù)不同的采樣規(guī)格分為最大池化與平均池化.池化層的作用是提取特征圖的局部特征,并對特征圖進行降維,減少模型的計算時間.最大池化的表達式為式(2),平均池化的表達式為式(3):
(2)
(3)
式(3)中的fout表示輸出圖像(i,j)位置的值,fin表示輸入圖像中(i,j)位置的值,p表示池化核的尺寸.
2.1.3 激活函數(shù)介紹
激活函數(shù)能夠?qū)斎氲募钸M行非線性轉(zhuǎn)換,通常跟在卷積層之后,使用激活函數(shù)能夠使網(wǎng)絡(luò)的表達能力變得更強大,而不是只能簡單的進行線性表達.常用的激活函數(shù)有Sigmoid函數(shù)、Tanh函數(shù)和ReLu函數(shù),它們的表達式分別為式(4)、式(5)、式(6).
(4)
(5)
Relu=max(0,x)
(6)
本文中卷積層使用直接卷積的方法進行計算,直接卷積需要在輸入圖像上進行劃窗操作,再將窗口截取到的矩陣與卷積核進行逐點累乘與累加,最后的累加值作為一次卷積的輸出值,隨著窗口在圖像上的滑動,最終完成對圖像的卷積計算.池化計算與卷積計算類似,也需要在輸入圖像上進行劃窗操作,但截取到的窗口矩陣不再進行累乘和累加計算,而是根據(jù)相應(yīng)的采樣規(guī)則計算窗口矩陣的值.由于卷積與池化都包含了劃窗這個操作,因此本文對電路進行復(fù)用,通過信號*arith_type來控制實現(xiàn)卷積與池化功能.
為實現(xiàn)劃窗操作,首先需要對輸入圖像進行行緩存,當(dāng)緩存所需窗口尺寸的行數(shù)后,再按列進行輸出,即可實現(xiàn)開窗的操作,隨著圖像數(shù)據(jù)的串行輸入,最終達到劃窗的效果.由于卷積與池化計算的輸入圖像尺寸是不確定的,不能采用常規(guī)的條狀移位寄存器來進行行緩存,本文中使用雙端口RAM來實現(xiàn)窗口的構(gòu)造,圖2是卷積與池化運算模塊設(shè)計框圖.將雙口RAM進行首尾相連,當(dāng)一個RAM緩存輸入圖像寬度個數(shù)據(jù)后,開始從當(dāng)前RAM讀取數(shù)據(jù)并寫入到下一個RAM中,當(dāng)最后一個RAM也緩存輸入圖像寬度個數(shù)據(jù)后,將所有RAM中的數(shù)據(jù)按列一拍一拍的輸出,同時,圖像繼續(xù)串行輸入,從而實現(xiàn)劃窗的操作.由于圖像的數(shù)據(jù)是串行輸入的,導(dǎo)致開窗后的數(shù)據(jù)矩陣與真正需要計算的矩陣是倒置的,因此需要將開窗截取到的數(shù)據(jù)矩陣進行一次重映射,重映射后的數(shù)據(jù)矩陣就是正確開窗后的矩陣.卷積核配置通過寫入模塊根據(jù)相關(guān)信號的控制,配置寄存器的個數(shù),形成卷積核矩陣,將從外部存儲器中讀取到的權(quán)重值按照順序?qū)懭氲郊拇婢矸e核矩陣中.當(dāng)卷積核與卷積域的數(shù)據(jù)都存放到相應(yīng)的寄存器后,將存放權(quán)重的寄存器矩陣與存放圖像數(shù)據(jù)的寄存器矩陣進行逐點乘法計算,將計算后的值存放到一個加法樹寄存器矩陣中.當(dāng)逐點乘法運算完成后,對加法樹矩陣進行基2加法樹運算,即每相鄰的兩個寄存器的值相加放到下一層的加法樹寄存器中,通過層層的加法運算,最終求得加法樹矩陣中所有值的和,即為一次窗口卷積的結(jié)果,配合前邊的劃窗操作,最終實現(xiàn)對圖像的卷積計算.
圖2 卷積與池化模塊設(shè)計框圖Fig.2 Convolution and pooling module design block diagram
對于池化運算,其劃窗操作與卷積運算的劃窗操作相同,只需要對卷積核中的數(shù)值進行配置即可實現(xiàn)池化運算.當(dāng)執(zhí)行最大池化運算時,通過卷積核配置模塊將卷積核寄存器中的值都配置為1,同時基2加法樹運算陣列不再是(a+b)運算,而是執(zhí)行max{a,b}運算;當(dāng)執(zhí)行平均池化運算時,通過卷積核配置模塊將卷積核寄存器中的值都配置為1,基2加法樹陣列執(zhí)行(a+b)運算,將最終的累加和使用定點除法器求商,作為最后的池化結(jié)果.當(dāng)執(zhí)行卷積計算與最大池化運算時,除法器的除數(shù)設(shè)置為1.
為了使卷積神經(jīng)網(wǎng)絡(luò)的表征能力更強,通常會在卷積計算之后使用激活函數(shù)進行非線性映射,常見的激活函數(shù)包括了:Sigmoid函數(shù)、Tanh函數(shù)和ReLU函數(shù).本文基于CORDIC算法設(shè)計了一種流水線結(jié)構(gòu)的激活函數(shù)計算模塊.激活函數(shù)計算過程中最復(fù)雜的就是指數(shù)計算,以exp指數(shù)計算為例,闡述基于CORDIC算法的流水線結(jié)構(gòu)的激活函數(shù)計算模塊的設(shè)計原理.CORDIC算法的迭代表達式為式(7).其中θk表示第k次旋轉(zhuǎn)的角度,dk表示第k次旋轉(zhuǎn)的方向,x,y表示坐標(biāo),z表示角度值.
(7)
圖3 流水線CORDIC算法實現(xiàn)框圖Fig.3 Pipeline CORDIC algorithm implementation block diagram
卷積神經(jīng)網(wǎng)絡(luò)中的Sigmoid函數(shù)和Tanh函數(shù)可以通過式(4)和式(5)的指數(shù)運算得到.因此為了實現(xiàn)Sigmoid函數(shù)與Tanh函數(shù)的流水線型計算,需要額外增加流水線型除法器.針對不同級的流水,通過CORDIC算法計算激活函數(shù)所消耗的資源,實現(xiàn)的精度有所不同,需要在精度與消耗的資源之間進行衡量.根據(jù)實驗測試發(fā)現(xiàn),選擇10級流水的CORDIC算法實現(xiàn)Sigmoid函數(shù)與Tanh函數(shù)的效果最好.
為了能夠?qū)Σ煌愋偷木矸e神經(jīng)網(wǎng)絡(luò)進行加速計算,本文設(shè)計了一種基于指令集架構(gòu)的神經(jīng)網(wǎng)絡(luò)協(xié)處理器,圖4為處理器的整體框圖.處理器采用指令的形式進行控制與計算,每一條指令的運算結(jié)果都以二維矩陣為粒度,每一行的運算結(jié)果都緩存在片上RAM中并最終寫入到片外存儲器中.處理器的運算指令需要固化在片內(nèi)RAM中,可以通過總線進行修改與配置,卷積神經(jīng)網(wǎng)絡(luò)中的權(quán)重值、輸入圖像的數(shù)據(jù)、中間的運算結(jié)果都通過多端口讀寫控制模塊存儲到片外存儲器中.
圖4 協(xié)處理器總體設(shè)計框架Fig.4 Coprocessor overall design framework
在卷積神經(jīng)網(wǎng)絡(luò)中,大多數(shù)運算都可以分為向量運算、標(biāo)量運算和矩陣運算[17],如加法、乘法、激活函數(shù)的運算可以看作是向量運算,矩陣乘法、點乘可以看作是矩陣運算,立即數(shù)的加減運算可以看作是標(biāo)量運算.因此本文將卷積神經(jīng)網(wǎng)絡(luò)的計算具體細分到了矩陣的加減法、乘法、非線性函數(shù)映射、二維圖像的卷積與池化運算、矩陣與立即數(shù)的加減運算等指令操作.為方便計算,本文中所有的運算數(shù)據(jù)都是32位有符號的定點運算,其中高16位表示整數(shù)位,低16位表示小數(shù)位.指令被設(shè)計為128位,指令結(jié)構(gòu)如表1所示.
表1 協(xié)處理器指令結(jié)構(gòu)說明Table 1 Coprocessor instruction structure description
其中[127∶124]表示操作碼;[123∶92]表示該指令輸入數(shù)據(jù)參數(shù)1的起始地址;[91∶60]表示該指令輸入數(shù)據(jù)參數(shù)2的起始地址;[59∶28]表示輸出數(shù)據(jù)參數(shù)3的起始地址;[27∶0]根據(jù)指令的不同分別用于表示圖像的尺寸,卷積核的尺寸等運算參數(shù).
本文設(shè)計指令執(zhí)行器,用于控制指令的順序執(zhí)行,不需要每執(zhí)行完一條指令就訪問外部處理器.在系統(tǒng)復(fù)位后,只需向神經(jīng)網(wǎng)絡(luò)協(xié)處理器發(fā)送一條啟動運算的指令,處理器就能夠按照順序?qū)⒅噶頡AM中的指令全部執(zhí)行一遍.指令順序執(zhí)行器的實現(xiàn)分為兩個步驟:1)將外部發(fā)送過來的指令存儲到指令RAM中;2)接收到啟動運算指令后,按照順序獲取指令RAM中的指令,當(dāng)指令全部執(zhí)行結(jié)束后,發(fā)出運算結(jié)束信號.整個指令順序執(zhí)行器設(shè)計框圖見圖5,主要有指令分析模塊和順序執(zhí)行狀態(tài)機組成.指令分析模塊需要對接收到的指令進行分析,如果是啟動指令,則通知順序執(zhí)行狀態(tài)機啟動神經(jīng)網(wǎng)絡(luò)計算模塊的指令調(diào)度.指令執(zhí)行狀態(tài)機在接收到指令分析模塊的啟動命令后,會循環(huán)給出指令的地址,并獲取指令,調(diào)度計算單元開始計算,直到所有指令執(zhí)行完成.
圖5 指令執(zhí)行器設(shè)計框圖Fig.5 Instruction executor design block diagram
順序執(zhí)行狀態(tài)機由IDLE、READ、SEND、DELAY、WAIT、ADDR這6個狀態(tài)組成,各個狀態(tài)與跳轉(zhuǎn)條件說明如下:
1)系統(tǒng)復(fù)位進入空閑狀態(tài)IDLE;
2)在IDLE狀態(tài),如果收到啟動運算信號,則會跳轉(zhuǎn)到READ狀態(tài);
3)在READ狀態(tài),等待3個時鐘完成指令讀取任務(wù),如果指令是無效指令,則跳轉(zhuǎn)到IDLE,否則進入SEND狀態(tài);
4)在SEND狀態(tài),將指令發(fā)送給計算單元,并給出指令有效信號,之后進入DELAY狀態(tài);
5)在DELAY狀態(tài),等待5個時鐘周期,使計算單元接收指令和指令有效信號,之后進入WAIT狀態(tài);
6)在WAIT狀態(tài),等待計算單元完成計算,在收到計算單元給出的完成信號后,之后進入ADDR狀態(tài);
7)在ADDR狀態(tài),對指令RAM的尋址地址加1,之后進入READ狀態(tài).
由于外部的DDR存儲器通常只有一個總線接口,而在系統(tǒng)中存在多個單元需要對存儲器進行讀寫,并且不同的單元對存儲器的訪問速度也可能不同.本文設(shè)計一種基于異步FIFO的多端口讀寫控制器,將DDR控制的單端口分時復(fù)用,從而實現(xiàn)多個端口對一個端口的讀寫控制功能,不同的端口之間存在著優(yōu)先級.圖6是2個端口寫和2個讀寫的控制器框架,想要實現(xiàn)更多的端口只需增加相應(yīng)的FIFO即可.
寫端口緩存與讀端口地址緩存有3個輸入信號,分別為:地址信號、請求信號和緩存余量信號;讀端口數(shù)據(jù)緩存有兩個輸出信號,分別為數(shù)據(jù)有效信號和數(shù)據(jù)讀完信號.對于寫端口,使用64bit寬度,深度為8的異步FIFO進行數(shù)據(jù)緩存,在FIFO中每個存儲空間存放32bit地址與32bit數(shù)據(jù);對于讀端口,使用32bit寬度,深度為8的異步FIFO進行緩存,在FIFO中每個存儲空間存放了要讀取的DDR地址.使用32bit寬度,深度為64 的異步FIFO緩存從DDR中讀取到的數(shù)據(jù).
圖6 多端口讀寫控制器設(shè)計框圖Fig.6 Multiport read-write controller design block diagram
讀寫端口選擇控制模塊主要由狀態(tài)機構(gòu)成,狀態(tài)機的跳轉(zhuǎn)邏輯如下:
1)系統(tǒng)復(fù)位后,狀態(tài)機進入0狀態(tài);
2)在0狀態(tài),首先使能所有的讀寫端口,并按照順序掃描不同的讀寫端口,如果某個端口的異步FIFO非空,根據(jù)端口序號跳轉(zhuǎn)到1~4不同狀態(tài);
3)在1狀態(tài),處理來自寫入端口#0的寫入請求,生成DDR相應(yīng)的寫地址、寫請求信號,在完成寫入操作后,撤銷DDR寫入請求,隨后屏蔽端口#0,使能其他端口,掃描是否有讀寫端口存在請求;
4)在2狀態(tài),處理來自讀取端口#1的讀取請求,生成DDR相應(yīng)的讀地址、讀請求信號,在完成數(shù)據(jù)的讀取后,撤銷DDR讀取請求,隨后屏蔽端口#1,使能其他端口,掃描是否有讀寫端口存在請求;
5)在3狀態(tài),處理來自寫入端口#2的寫入請求,生成DDR相應(yīng)的寫地址、寫請求信號,在完成寫入操作后,撤銷DDR寫入請求,隨后屏蔽端口#2,使能其他端口,掃描是否有讀寫端口存在請求;
6)在4狀態(tài),處理來自讀取端口#3的讀取請求,生成DDR相應(yīng)的讀地址、讀請求信號,在完成數(shù)據(jù)的讀取后,撤銷DDR讀取請求,隨后屏蔽端口#3,使能其他端口,掃描是否有讀寫端口存在請求;
為了區(qū)分讀數(shù)據(jù)信號與讀數(shù)據(jù)有效信號對應(yīng)讀取端口#1還是讀取端口#3,使用一個4bit寬度,深度為64的異步FIFO進行讀取端口選擇的緩存,運行時鐘與端口選擇控制模塊時鐘相同.使用多端口控制器進行讀寫端口的擴展,要求各個讀寫端口盡可能的發(fā)起連續(xù)地址的讀寫請求,以達到最大的DDR讀寫帶寬利用率.每次端口選擇控制模塊切換端口的周期計算為:
(8)
其中,Ts為切換端口的周期;Nf為當(dāng)前FIFO在被選中時刻的深度,Wf為FIFO的位寬,F(xiàn)d為控制器的工作頻率,Wd為內(nèi)存的位寬,Ed為控制器的讀寫效率.
協(xié)處理器中的運算邏輯在神經(jīng)網(wǎng)絡(luò)計算單元中實現(xiàn),計算單元由運算控制邏輯、指令解析邏輯、指令運算邏輯和DDR讀寫接口等部分組成.如果計算單元準(zhǔn)備就緒,就會發(fā)出Ready信號,表示可以接收運算指令,在接收到指令和指令有效信號后,解析指令的執(zhí)行類型并由控制邏輯控制計算單元開始數(shù)據(jù)的讀取與指令的運算,神經(jīng)網(wǎng)絡(luò)計算單元設(shè)計框圖見圖7.讀寫地址生成模塊用于產(chǎn)生讀寫操作時DDR中的數(shù)據(jù)的地址,回寫緩存模塊用于緩存每條指令計算的結(jié)果.
圖7 神經(jīng)網(wǎng)絡(luò)計算單元設(shè)計框圖Fig.7 Design block diagram of neural network computing unit
根據(jù)指令類型的不同,計算任務(wù)可以劃分為雙矩陣逐點運算(矩陣的加法、減法和點積運算)、單矩陣逐點運算(矩陣與立即數(shù)的加法、減法、乘法運算以及激活函數(shù)的計算)、矩陣轉(zhuǎn)置運算、矩陣乘法運算和圖像的卷積與池化運算等任務(wù).不同任務(wù)對數(shù)據(jù)的讀寫與運算方式不同,任務(wù)間的轉(zhuǎn)換通過運算控制邏輯實現(xiàn).運算控制邏輯主要由有限狀態(tài)機構(gòu)成,包含了執(zhí)行不同任務(wù)的子狀態(tài)機.當(dāng)系統(tǒng)復(fù)位時,控制邏輯處于空閑狀態(tài),接收到指令后,根據(jù)Opcode的編碼跳轉(zhuǎn)到相應(yīng)任務(wù)的子狀態(tài)機中,通過子狀態(tài)機控制對數(shù)據(jù)的讀寫與運算.
為提高運算的效率,執(zhí)行每個任務(wù)時進行邊讀邊寫的操作.執(zhí)行雙矩陣逐點運算任務(wù)時,先讀取參數(shù)1的一行數(shù)據(jù),然后讀取參數(shù)2的一行數(shù)據(jù),同時每讀取參數(shù)2的一個數(shù)據(jù)便與對應(yīng)的參數(shù)1的數(shù)據(jù)進行逐點運算,并將結(jié)果進行緩存,當(dāng)一行數(shù)據(jù)全部計算完成后將結(jié)果寫回到DDR,之后開始讀取下一行的數(shù)據(jù),直到整個矩陣全部讀取完成.執(zhí)行單矩陣逐點運算任務(wù)時,只要先讀取參數(shù)1的數(shù)據(jù),進行相應(yīng)的流水線運算,對一行的數(shù)據(jù)逐點進行相應(yīng)運算的同時寫回到DDR,當(dāng)一行數(shù)據(jù)計算完成后繼續(xù)讀取下一行的數(shù)據(jù),直到參數(shù)1的數(shù)據(jù)全部計算完成.執(zhí)行矩陣轉(zhuǎn)置任務(wù)時,為保證寫回的數(shù)據(jù)是按行連續(xù)的,因此在讀取數(shù)據(jù)時優(yōu)先按列讀取參數(shù)1指示的數(shù)據(jù),并直接按行寫回到DDR,直到整個矩陣完整轉(zhuǎn)置.執(zhí)行矩陣乘法任務(wù)時,需要先讀取參數(shù)1指示數(shù)據(jù)的某一行,之后依次讀取參數(shù)2指示數(shù)據(jù)的每一列,在讀取參數(shù)2指示數(shù)據(jù)的同時進行乘累加運算,將結(jié)果進行緩存,當(dāng)參數(shù)2 指示數(shù)據(jù)的每一列都讀取完成后,將運算結(jié)果寫回到DDR,并開始讀取參數(shù)1指示數(shù)據(jù)的下一行,直到參數(shù)1指示的數(shù)據(jù)完全讀取.
本文中的實驗使用Tensorflow[18]深度學(xué)習(xí)框架搭建卷積神經(jīng)網(wǎng)絡(luò),網(wǎng)絡(luò)結(jié)構(gòu)如表2,在Windows10環(huán)境下,使用Intel I5 9400 CPU+GTX1070 GPU在MNIST數(shù)據(jù)集[19]上進行訓(xùn)練,在PYNQ-Z2開發(fā)板進行前向推理.PYNQ-Z2開發(fā)板的芯片型號為Xilinx 的XC7Z020-1CLG400C,主要的內(nèi)部資源分為PS、PL和外設(shè)等部分,PS端包括雙核ARM Cortex-A9處理器,工作頻率為650MHz,PL端包括1.3M邏輯片,220個DSPs,同時開發(fā)板包括512MB16位總線寬度的DDR3存儲器,最高工作頻率為1050Mbps.
表2 卷積神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)說明Table 2 Convolutional neural network structure description
為驗證神經(jīng)網(wǎng)絡(luò)計算單元指令集運算的準(zhǔn)確性,本文使用Python與UVM驗證方法學(xué)搭建指令運算驗證平臺,使用Modelsim軟件進行仿真,驗證平臺結(jié)構(gòu)如圖8所示.首先使用Python讀取卷積神經(jīng)網(wǎng)絡(luò)模型結(jié)構(gòu)文件,通過解析各個層的種類,生成相應(yīng)的處理器運算指令;之后使用Python讀取卷積神經(jīng)網(wǎng)絡(luò)模型參數(shù)文件,將這些參數(shù)量化為32位有符號定點數(shù),分配到不同的內(nèi)存地址,并生成DDR初始化文件.使用Modelsim加載生成的指令文件對指令RAM存儲模型進行初始化,之后加載DDR初始化文件將模型的參數(shù)初始化到DDR仿真模型中.通過將Monitor接收到的運算結(jié)果與在Tensorflow中模型的運算結(jié)果進行對比,驗證指令運算的準(zhǔn)確性,并對計算誤差進行統(tǒng)計.
通過搭建的指令運算驗證平臺,可以精準(zhǔn)地知道神經(jīng)網(wǎng)絡(luò)協(xié)處理器在運算過程中每一步和最終的計算結(jié)果,以及與單精度浮點數(shù)運算相比,由精度損失導(dǎo)致的相對誤差.通過進行大量指令運算,將運算結(jié)果的相對誤差進行統(tǒng)計,圖9是部分指令的計算相對誤差.通過統(tǒng)計發(fā)現(xiàn),加法、點乘、乘法和卷積等指令的運算結(jié)果相對誤差控制在10-4級別,激活函數(shù)的計算相對誤差控制在0.05以下,滿足神經(jīng)網(wǎng)絡(luò)協(xié)處理器的運算需求.
圖8 協(xié)處理器驗證平臺Fig.8 Coprocessor verification platform
圖9 部分指令運算誤差統(tǒng)計Fig.9 Partial instruction operation error statistics
使用vivado 2018.3軟件對設(shè)計進行綜合與時序分析,在100MHz的工作頻率下,通過時序分析,確定設(shè)計中各條關(guān)鍵路徑均滿足時序要求.表3是設(shè)計中各個模塊的資源消耗情況,BRAMs表示消耗的塊RAM;LUTs表示消耗的邏輯資源;DSPs表示消耗的DSP的數(shù)量.計算單元中存在卷積、矩陣乘法等運算,消耗較多的DSP,而BRAM主要用于行緩存與指令的存儲,多端口讀寫模塊使用純邏輯單元實現(xiàn).
表3 設(shè)計中各模塊資源消耗Table 3 Resource consumption of each module in the design
將設(shè)計下載到PYNQ-Z2開發(fā)板上對MINST數(shù)據(jù)集進行分類識別,準(zhǔn)確率達98%以上,達到主流的識別準(zhǔn)確率.表4是本設(shè)計與其他卷積神經(jīng)網(wǎng)絡(luò)處理器的FPGA實現(xiàn)的結(jié)果對比,為更加全面公平的比對加速效果,增加能效比參數(shù).
表4 與文獻中的方案對比Table 4 Compared with the scheme in the literature
從表4中可以看出,本設(shè)計的能效為19.87GOPS.W-1,消耗24663LUTs,與文獻[4]的設(shè)計相比,本文的設(shè)計能效降低30%左右,消耗的資源降低60%;與文獻[11]的設(shè)計相比,本文的設(shè)計在達到相當(dāng)能效的條件下,消耗的資源降低80%左右;與文獻[20]的設(shè)計相比,本文的設(shè)計能效提高40倍,消耗的資源降低70%左右.本文的設(shè)計在達到同類設(shè)計的主流水平時,消耗的邏輯資源僅為同類設(shè)計的20%,消耗的DSP資源為同類設(shè)計的20%.
本文提出一種在FPGA平臺上實現(xiàn)指令集架構(gòu)的神經(jīng)網(wǎng)絡(luò)協(xié)處理器的方案,可通過對不同神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)的解析,生成計算指令,能靈活實現(xiàn)復(fù)雜神經(jīng)網(wǎng)絡(luò)在FPGA平臺上的加速計算,縮短神經(jīng)網(wǎng)絡(luò)部署的時間;并通過硬件電路結(jié)構(gòu)的分時復(fù)用,減少對資源的消耗.方案中使用Python與UVM驗證方法學(xué)搭建驗證平臺,驗證了指令計算的誤差在10-4級別,滿足運算的需求,通過在PYNQ-Z2開發(fā)板上測試,運算能效為19.87GOPS.W-1,達到同級別設(shè)計主流水平,消耗的資源比同級別產(chǎn)品平均降低80%.本方案中的運算使用的數(shù)據(jù)位寬為32位,為更好的降低功耗,提高計算的并行度,在后續(xù)的研究與設(shè)計中,可考慮使用16位或8位的數(shù)據(jù)進行運算.