廖裕民
(福州瑞芯微電子有限公司,福州350003)
隨著深度學(xué)習(xí)的快速發(fā)展與應(yīng)用[1-2],卷積神經(jīng)網(wǎng)絡(luò)(Convolutional Neural Network,CNN)正在被越來(lái)越廣泛的使用,特別是在圖像識(shí)別和分類場(chǎng)景中獲得了巨大的突破性進(jìn)展。CNN 由于擁有多層的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu),其自身有很強(qiáng)的學(xué)習(xí)和并行處理特點(diǎn)[3],是一種擁有多層感知,局部連接和權(quán)值共享的網(wǎng)絡(luò)結(jié)構(gòu)[4],所以最終可以達(dá)到較低的網(wǎng)絡(luò)模型復(fù)雜性和較少的網(wǎng)絡(luò)連接權(quán)值個(gè)數(shù),因此近年來(lái),越來(lái)越多的CNN 正在被圖像內(nèi)容分析[5-6]、內(nèi)容識(shí)別[7-8]等領(lǐng)域得到了廣泛的應(yīng)用。但是隨著CNN 的逐步廣泛應(yīng)用,其海量的運(yùn)算能力需求與當(dāng)前硬件運(yùn)算能力的矛盾越來(lái)越突出。在現(xiàn)階段實(shí)現(xiàn)卷積神經(jīng)網(wǎng)絡(luò)主要還是使用消費(fèi)級(jí)的通用處理器CPU 或者GPU 來(lái)實(shí)現(xiàn),其運(yùn)算效率較低且能耗非常高,因此這還遠(yuǎn)遠(yuǎn)不能滿足卷積神經(jīng)網(wǎng)絡(luò)運(yùn)算對(duì)速度和低能耗的需求。
同時(shí),由于便攜電子設(shè)備的普及,神經(jīng)網(wǎng)絡(luò)運(yùn)算對(duì)便攜化的需求也非常強(qiáng)烈,但是便攜設(shè)備對(duì)功耗和工作效率要求非常高[9-10],所以我們提出了這個(gè)通用低功耗高效率的CNN 加速電路結(jié)構(gòu),對(duì)可重構(gòu)和工作效率和功耗都做了針對(duì)性的優(yōu)化設(shè)計(jì),以到達(dá)到便攜設(shè)備的要求。
本文提出的加速電路具備以下特點(diǎn):
(1)通過(guò)可重構(gòu)性設(shè)計(jì)方法,讓電路可以兼容多種神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)和算法,使得這套電路不僅可以完全實(shí)現(xiàn)前面提到的多種神經(jīng)網(wǎng)絡(luò)圖像算法,還可以對(duì)將來(lái)的算法升級(jí)有良好的適應(yīng)性。
(2)通過(guò)雙配置寄存器組設(shè)計(jì),減少模塊的空閑時(shí)間,從而提高模塊的利用率。
(3)通過(guò)利用圖像卷積運(yùn)算中數(shù)據(jù)稀疏性的特點(diǎn)做了針對(duì)性的低功耗設(shè)計(jì),使得該加速電路可以運(yùn)行在較低功耗水平,以適應(yīng)移動(dòng)手持設(shè)備的需求。
整體的電路結(jié)構(gòu)由以下幾個(gè)部分構(gòu)成:主存儲(chǔ)器、CPU、取數(shù)控制模塊、卷積運(yùn)算模塊、激活運(yùn)算模塊、池化運(yùn)算模塊、寫數(shù)控制模塊,以及每個(gè)運(yùn)算模塊都帶有一個(gè)直通單元和寄存器通路選擇單元。
圖1 電路總結(jié)構(gòu)
神經(jīng)網(wǎng)絡(luò)運(yùn)算加速電路的連接結(jié)構(gòu)和工作流程如下:
運(yùn)算加速電路由于采用可重構(gòu)性的設(shè)計(jì)結(jié)構(gòu),將神經(jīng)網(wǎng)絡(luò)電路算法拆分為多個(gè)小的運(yùn)算加速模塊單元,通過(guò)通路配置使其可以適配各種不同的網(wǎng)絡(luò)結(jié)構(gòu)。因此該運(yùn)算加速芯片可以完成各種深度學(xué)習(xí)神經(jīng)網(wǎng)絡(luò)處理中所需的圖像邊沿分割和內(nèi)容分類等多個(gè)算法加速運(yùn)算。
神經(jīng)網(wǎng)絡(luò)運(yùn)算加速電路包括:主存儲(chǔ)器、CPU、取數(shù)控制模塊、卷積運(yùn)算模塊、激活運(yùn)算模塊、池化運(yùn)算模塊、寫數(shù)控制模塊,以及每個(gè)運(yùn)算模塊都帶有一個(gè)直通單元和寄存器通路選擇單元的設(shè)計(jì)。
其中,除了讀寫控制兩個(gè)模塊之外,中間的每個(gè)模塊都有一個(gè)直通單元,直通單元負(fù)責(zé)根據(jù)配置將數(shù)據(jù)流跳過(guò)對(duì)應(yīng)模塊直接到達(dá)下一個(gè)運(yùn)算模塊,以實(shí)現(xiàn)不同的網(wǎng)絡(luò)結(jié)構(gòu)。
在電路的工作前需要先完成算法的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)訓(xùn)練以產(chǎn)生完整的網(wǎng)絡(luò)結(jié)構(gòu)和所有的網(wǎng)絡(luò)參數(shù),然后將網(wǎng)絡(luò)結(jié)構(gòu)和網(wǎng)絡(luò)參數(shù)存入主存儲(chǔ)器中,以便運(yùn)算加速芯片進(jìn)行加速運(yùn)算。當(dāng)所有網(wǎng)絡(luò)結(jié)果和參數(shù)存入主存儲(chǔ)器后,整個(gè)電路可以開始正常工作。
主存儲(chǔ)器存儲(chǔ)了網(wǎng)絡(luò)結(jié)構(gòu)和網(wǎng)絡(luò)參數(shù),包括網(wǎng)絡(luò)層數(shù)量,每層網(wǎng)絡(luò)卷積核個(gè)數(shù)、寬度、高度、通道數(shù)、卷積步長(zhǎng)、PADDING 大小、卷積核數(shù)值、激活函數(shù)類型、池化大小參數(shù)等。同時(shí)主存儲(chǔ)器還負(fù)責(zé)存儲(chǔ)網(wǎng)絡(luò)層間的中間運(yùn)算結(jié)果。
CPU 在電路開始工作后,從主存儲(chǔ)器中讀取出網(wǎng)絡(luò)結(jié)構(gòu)參數(shù)對(duì)各個(gè)模塊的配置寄存器進(jìn)行配置控制,根據(jù)網(wǎng)絡(luò)結(jié)構(gòu)選擇需要的模塊,將不需要的模塊通過(guò)配置該模塊的直通單元有效而使其被繞過(guò)。
在CPU 配置完成后,取數(shù)控制單元,根據(jù)配置寄存器信息對(duì)存儲(chǔ)器進(jìn)行特征數(shù)據(jù)和卷積核數(shù)據(jù)的讀取操作,并把讀取數(shù)據(jù)送往卷積運(yùn)算模塊。
卷積運(yùn)算模塊:對(duì)特征數(shù)據(jù)和卷積核進(jìn)行神經(jīng)網(wǎng)絡(luò)的卷積運(yùn)算和反卷積運(yùn)算,該電路在設(shè)計(jì)時(shí)充分考慮了圖像卷積運(yùn)算中數(shù)據(jù)稀疏性的特點(diǎn)做了針對(duì)性的低功耗設(shè)計(jì),使得該加速電路可以運(yùn)行在較低功耗水平。具體結(jié)構(gòu)后面有詳述。
激活運(yùn)算模塊:可以進(jìn)行神經(jīng)網(wǎng)絡(luò)的激活函數(shù)運(yùn)算,支持ReLU、PReLU、sigmoid 激活函數(shù)。
反池化模塊:可以進(jìn)行反卷積運(yùn)算,將結(jié)果送往池化運(yùn)算模塊。
池化運(yùn)算模塊:可以完成神經(jīng)網(wǎng)絡(luò)的池化運(yùn)算,將池化運(yùn)算結(jié)果送往寫數(shù)控制模塊。
為了提高整個(gè)神經(jīng)網(wǎng)絡(luò)加速運(yùn)算的工作效率,減少網(wǎng)絡(luò)層之間的運(yùn)算時(shí)間間隔,我們?cè)O(shè)計(jì)了一種雙寄存器組結(jié)構(gòu),該結(jié)構(gòu)為每個(gè)運(yùn)算模塊都設(shè)計(jì)了AB 兩組配置寄存器和一個(gè)寄存器選通控制單元,分別可以存儲(chǔ)兩層網(wǎng)絡(luò)的配置。
圖2 正常NN 加速電路工作流程
圖2 是正常情況下的神經(jīng)網(wǎng)絡(luò)加速運(yùn)算流程,下一層的運(yùn)算依賴于前一層運(yùn)算的全部結(jié)束,可以看到每個(gè)模塊實(shí)際工作中都會(huì)存在大量的空閑。
為了解決這個(gè)問(wèn)題,提升加速電路的工作效率,減少電路的空閑時(shí)間,我們?yōu)槊總€(gè)運(yùn)算模塊都設(shè)計(jì)了AB兩組配置寄存器和一個(gè)寄存器選通控制單元,使得各個(gè)模塊工作時(shí)不再依賴于前一網(wǎng)絡(luò)層運(yùn)算完畢,而是自己模塊完成當(dāng)前層的運(yùn)算后可以立即切換到下一層的運(yùn)算,達(dá)到圖3 中的工作效果。
雙寄存器組的具體工作方式:
(1)在加速電路開始工作前,CPU 先將前兩層網(wǎng)絡(luò)的配置分別配置到每個(gè)模塊的配置寄存器A 和配置寄存器B。然后加速電路可以開始工作,工作開始后首先使用配置寄存器A 中的配置進(jìn)行第一層網(wǎng)絡(luò)的工作。
(2)當(dāng)?shù)谝粋€(gè)模塊完成當(dāng)前層的工作后,將本層工作完成信號(hào)送往本模塊的寄存器選通控制單元和CPU,然后本模塊的寄存器選通控制單元立刻將該模塊的寄存器改為寄存器B 也就是下一個(gè)網(wǎng)絡(luò)層的配置,該模塊可以立刻進(jìn)入下一層的工作處理。同時(shí),CPU 在收到該模塊的本層工作完成信號(hào)后,對(duì)寄存器A 中的配置進(jìn)行配置更新,更新為第三層網(wǎng)絡(luò)的配置。
(3)當(dāng)模塊完成第二層網(wǎng)絡(luò)的運(yùn)算工作后,同樣的將本層工作完成信號(hào)送往本模塊的寄存器選通控制單元和CPU,然后本模塊的寄存器選通控制單元立刻將該模塊的寄存器改為寄存器A 也就是第三層網(wǎng)絡(luò)的配置,該模塊可以立刻進(jìn)入第三層的工作處理。同時(shí),CPU 在收到該模塊的本層工作完成信號(hào)后,對(duì)寄存器B 中的配置進(jìn)行配置更新,更新為第四層網(wǎng)絡(luò)的配置。
(4)每個(gè)模塊都遵照上面所述的順序進(jìn)行工作,不依賴于整層網(wǎng)絡(luò)運(yùn)算結(jié)束后整體切換到下一層進(jìn)行工作,實(shí)現(xiàn)了完全流水作業(yè),大幅減少了各模塊的空閑狀態(tài)時(shí)間,從而提升了的電路工作效率。
圖3 雙寄存器組電路工作流程
由于大量的神經(jīng)網(wǎng)絡(luò)運(yùn)算圖像具有稀疏性的特點(diǎn)。因此我們針對(duì)待運(yùn)算圖像中出現(xiàn)的數(shù)據(jù)稀疏性矩陣運(yùn)算特點(diǎn),設(shè)計(jì)了針對(duì)性的功耗優(yōu)化和運(yùn)算電路。該電路可以有效地降低卷積神經(jīng)網(wǎng)絡(luò)電路運(yùn)算過(guò)程中的運(yùn)算數(shù)量和運(yùn)算過(guò)程中消耗的功耗。
卷積層是所有神經(jīng)網(wǎng)絡(luò)運(yùn)算中最重要也隨耗費(fèi)硬件資源和功耗的部分,卷積運(yùn)算的計(jì)算公式如下:
Fi=σ(Wc(i)*Fi-1+bi).
其中,F(xiàn)i表示第i 卷積層的卷積結(jié)果,F(xiàn)i-1表示第i-1 卷積層的卷積結(jié)果,Wc(i)表示第i 卷積層的權(quán)值,符號(hào)“*”表示卷積運(yùn)算,bi表示第i 卷積層的偏置,σ表示激活函數(shù)運(yùn)算。
針對(duì)圖像的稀疏性,本文提出的針對(duì)性優(yōu)化的卷積運(yùn)算電路結(jié)構(gòu)如圖4。
在乘加陣列的設(shè)計(jì)上,將32 個(gè)乘加器劃分為4 個(gè)時(shí)鐘組,每個(gè)時(shí)鐘組包含相同數(shù)量的8 個(gè)乘加器單元。然后通過(guò)對(duì)待運(yùn)算的特征數(shù)據(jù)和卷積核數(shù)據(jù)進(jìn)行非零判斷,如果特征數(shù)據(jù)或者卷積核數(shù)據(jù)值任意一個(gè)為零則表示該次運(yùn)算的結(jié)果必然為零,因此只對(duì)該次運(yùn)算的位置進(jìn)行標(biāo)記而不做乘加運(yùn)算,當(dāng)完成整個(gè)待運(yùn)算矩陣的非零判斷后,根據(jù)剩下的非零運(yùn)算的數(shù)量來(lái)判斷需要打開多少個(gè)時(shí)鐘組的乘加單元,而不需要用到的時(shí)鐘組在此次運(yùn)算中時(shí)鐘始終處于關(guān)閉狀態(tài),最后在運(yùn)算完成后,根據(jù)前面非零判斷時(shí)對(duì)零數(shù)據(jù)的位置進(jìn)行恢復(fù)后完成后累加,從而實(shí)現(xiàn)了低功耗的卷積運(yùn)算處理。
乘加陣列單元的具體工作過(guò)程:
(1)兩個(gè)非零判斷單元分別負(fù)責(zé)對(duì)特征數(shù)據(jù)和卷積核中的數(shù)據(jù)進(jìn)行非零判斷,如果數(shù)據(jù)為零,則輸出高有效信號(hào)到邏輯“或”電路。
(2)邏輯“或”電路負(fù)責(zé)對(duì)兩個(gè)非零判斷單元的判斷結(jié)果進(jìn)行邏輯“或”操作,將運(yùn)算結(jié)果送往非零統(tǒng)計(jì)單元和通路開關(guān)和分配單元。因?yàn)榱愠艘匀魏螖?shù)都為零,所以只要待相乘的兩個(gè)數(shù)中任何一個(gè)為零則運(yùn)算結(jié)果必然為零,所以在此使用了或操作。
(3)非零統(tǒng)計(jì)單元負(fù)責(zé)對(duì)邏輯“或”電路輸出的特征數(shù)據(jù)和卷積核數(shù)據(jù)都非零的操作數(shù)進(jìn)行統(tǒng)計(jì),并將統(tǒng)計(jì)數(shù)據(jù)送往門控時(shí)鐘單元。
(4)通路開關(guān)負(fù)責(zé)根邏輯“或”電路輸出的判斷結(jié)果,在特征數(shù)據(jù)和卷積核數(shù)據(jù)都非零時(shí)將數(shù)據(jù)送往分配單元。在有零時(shí),不將數(shù)據(jù)送往分配單元。
(5)分配單元根據(jù)通路開關(guān)送來(lái)的數(shù)據(jù),依次送往每個(gè)乘加陣列組,例如先送組1 的8 個(gè)乘加器,然后再是組2 的8 個(gè)乘加器,直到送滿整個(gè)乘加陣列。同時(shí)并將該非零數(shù)據(jù)在特征數(shù)據(jù)流中的序號(hào)送往非零數(shù)據(jù)序號(hào)存儲(chǔ)單元。而從實(shí)現(xiàn)了將整個(gè)序列中的非零數(shù)據(jù)重新整齊排列到規(guī)整緩存單元中,并將這些非零數(shù)據(jù)的序號(hào)送往累加緩存單元以方便累加時(shí)還原矩陣位置。
圖4 卷積運(yùn)算電路結(jié)構(gòu)
(6)門控時(shí)時(shí)鐘判斷單元根據(jù)非零數(shù)據(jù)個(gè)數(shù)和乘加陣列的每個(gè)門控時(shí)鐘控制的乘加器組中乘加器的個(gè)數(shù),來(lái)決定打開幾個(gè)乘加器組的時(shí)鐘。
(7)乘加器單元負(fù)責(zé)對(duì)特征數(shù)據(jù)和卷積核數(shù)據(jù)進(jìn)行乘加運(yùn)算操作,并將乘加結(jié)果送往累加緩存單元。
(8)累加緩存單元在乘加器單元完成乘加運(yùn)算后,從非零數(shù)據(jù)序號(hào)存儲(chǔ)單元讀取本次乘加運(yùn)算結(jié)果對(duì)應(yīng)的矩陣位置點(diǎn),完成后對(duì)乘加結(jié)果的累加操作。
(9)直到整個(gè)卷積核的全部channel 完成累加,此時(shí)的累加結(jié)果作為最終卷積結(jié)果輸出。
通過(guò)以上提出的神經(jīng)網(wǎng)絡(luò)加速電路,可以快速完成各種神經(jīng)網(wǎng)絡(luò)算法加速處理。
為了測(cè)試本文提出的電路結(jié)構(gòu),我們采用LeNet網(wǎng)絡(luò)結(jié)構(gòu)進(jìn)行實(shí)驗(yàn),如圖5 所示,網(wǎng)絡(luò)包含卷積、激活、池化等運(yùn)算,對(duì)應(yīng)于硬件的卷積運(yùn)算模塊、激活運(yùn)算模塊、池化運(yùn)算模塊,同時(shí)可分為4 層運(yùn)算。作為硬件運(yùn)算結(jié)果的對(duì)比參考值,本文使用TensorFlow 對(duì)網(wǎng)絡(luò)進(jìn)行網(wǎng)絡(luò)搭建和參數(shù)訓(xùn)練,將權(quán)重等參數(shù)載入主存儲(chǔ)器,通過(guò)C 代碼控制CPU 配置神經(jīng)網(wǎng)絡(luò)運(yùn)算加速芯片,最終得到運(yùn)算結(jié)果。
然后,根據(jù)本文提出的結(jié)構(gòu),使用硬件描述語(yǔ)言Verilog 完成了電路的設(shè)計(jì)實(shí)現(xiàn),在VCS 仿真工具下進(jìn)行功能仿真正確后,經(jīng)過(guò)Quartus 綜合,將網(wǎng)表下載到FPGA 器件Stratix IV EP4SE820 中,具體實(shí)驗(yàn)流程如下:
開始的準(zhǔn)備工作:
首先,準(zhǔn)備好待處理圖像數(shù)據(jù),和電路實(shí)現(xiàn)的算法對(duì)應(yīng)的TensorFlow 算法模型;
然后,將待處理圖像數(shù)據(jù)經(jīng)過(guò)TensorFlow 算法模型的計(jì)算得到參考正確結(jié)果。此時(shí),準(zhǔn)備工作結(jié)束。
正式試驗(yàn)流程:
首先,將待處理圖像數(shù)據(jù)和網(wǎng)絡(luò)參數(shù)初始化到RAM 中;
然后,打開神經(jīng)網(wǎng)絡(luò)加速電路使其開始工作,加速電路讀取RAM 中的待處理圖像和網(wǎng)絡(luò)參數(shù)進(jìn)行神經(jīng)網(wǎng)絡(luò)層運(yùn)算處理后將該層的數(shù)據(jù)結(jié)果寫回RAM 的另一段地址。然后開始讀入下一層的網(wǎng)絡(luò)參數(shù)和上一層的運(yùn)算結(jié)果開始下一層的運(yùn)算,如此循環(huán)直到所有網(wǎng)絡(luò)層完成運(yùn)算和結(jié)果導(dǎo)出。
最后,將經(jīng)過(guò)神經(jīng)網(wǎng)絡(luò)加速電路處理后的RAM 中的結(jié)果數(shù)據(jù)導(dǎo)出,并且和之前準(zhǔn)備的參考正確結(jié)果進(jìn)行比對(duì),則可以判斷電路是否可以正確工作。
實(shí)驗(yàn)結(jié)果表明本文設(shè)計(jì)的神經(jīng)網(wǎng)絡(luò)加速電路在FPGA 上對(duì)100 幅測(cè)試圖像進(jìn)行測(cè)試,測(cè)試精度為95%,與算法運(yùn)算結(jié)果完全一致。
本文提出了一套通用低功耗高效率的CNN 加速電路結(jié)構(gòu)。該結(jié)構(gòu)具有可重構(gòu)、工作效率高、低功耗的特點(diǎn),可以快速完成各種神經(jīng)網(wǎng)絡(luò)算法的圖像處理,同時(shí)可以滿足便攜設(shè)備的功耗和性能需求。
圖5 LeNet網(wǎng)絡(luò)結(jié)構(gòu)