(中國(guó)科學(xué)技術(shù)大學(xué) 計(jì)算機(jī)科學(xué)與技術(shù)學(xué)院,安徽 合肥 230027)
作為現(xiàn)代人工智能的重要分支,人工神經(jīng)網(wǎng)絡(luò)(artificial neural network,簡(jiǎn)稱ANN)近年來(lái)得到迅速發(fā)展.深度學(xué)習(xí)作為其在大數(shù)據(jù)時(shí)代背景下的延續(xù)和進(jìn)化,通過(guò)增加網(wǎng)絡(luò)模型的深度,有效增強(qiáng)了傳統(tǒng)ANN 算法的數(shù)據(jù)特征提取能力.其中,卷積神經(jīng)網(wǎng)絡(luò)(CNN)作為深度學(xué)習(xí)中廣泛采用的算法,被人們實(shí)現(xiàn)在如人臉識(shí)別[1]、目標(biāo)檢測(cè)[2]、語(yǔ)音識(shí)別[3]、自然語(yǔ)言理解[4]等應(yīng)用中,并取得了令人矚目的成果.得益于其在各類應(yīng)用場(chǎng)景中的出色表現(xiàn),CNN 已成為研究人員關(guān)注的重點(diǎn),并廣泛部署在數(shù)據(jù)中心以及邊緣嵌入式設(shè)備中.
然而,CNN 出色的識(shí)別精度背后是不斷加深、復(fù)雜的網(wǎng)絡(luò)結(jié)構(gòu)和巨大的計(jì)算、訪存量.近年來(lái),CNN 模型的參數(shù)量達(dá)到了百萬(wàn)級(jí)別,計(jì)算量達(dá)到千兆級(jí)別[5-7].CNN 密集的計(jì)算和訪存也給通用處理器帶來(lái)了巨大的壓力.因此,近年來(lái)涌現(xiàn)了許多基于FPGA[8-10]、GPU[5]和ASIC[11,12]的加速器,并達(dá)到了優(yōu)于CPU 的性能和能效.在這3 類平臺(tái)中,相比于動(dòng)輒消耗數(shù)十瓦甚至數(shù)百瓦的GPU 平臺(tái),FPGA 和ASIC 通常具有更低的功耗.盡管GPU 在CNN 模型的訓(xùn)練階段具有獨(dú)特的優(yōu)勢(shì),但離線訓(xùn)練以進(jìn)行在線預(yù)測(cè)的模式使得模型推理過(guò)程更加關(guān)鍵.而在推理過(guò)程中,FPGA、ASIC 的低功耗特性使其具有更廣泛的應(yīng)用領(lǐng)域,如電量受限的嵌入式平臺(tái).因此本文主要關(guān)注基于這兩類平臺(tái)的CNN 加速器的相關(guān)工作.但經(jīng)觀察發(fā)現(xiàn),先前的工作中此類加速器通常僅加速特定的網(wǎng)絡(luò)結(jié)構(gòu)或特定類型的層,模式相對(duì)固定,靈活性較低.
為了解決這一問(wèn)題,陳云霽團(tuán)隊(duì)提出了DianNao[11],一款針對(duì)不同機(jī)器學(xué)習(xí)應(yīng)用的高吞吐量ASIC 芯片,并設(shè)計(jì)了超長(zhǎng)指令字(very long instruction word,簡(jiǎn)稱VLIW)風(fēng)格的指令,其支持CNN 和多層感知機(jī)模型(multilayer perceptrons,簡(jiǎn)稱MLPs).相繼提出的DaDianNao[13]則是在DianNao 基礎(chǔ)上的SIMD 實(shí)現(xiàn),不同之處在于用于計(jì)算的權(quán)值矩陣固化到本地的eDRAM 上,減少了讀取內(nèi)存的次數(shù).但兩者中VLIW 風(fēng)格指令對(duì)計(jì)算過(guò)程的抽象較差,若不了解底層硬件,則難以使用.隨后,該團(tuán)隊(duì)通過(guò)對(duì)ANN 中的計(jì)算進(jìn)行抽象,設(shè)計(jì)了專用指令集Cambricon[14],其包含了標(biāo)量、向量和矩陣等指令,支持多種神經(jīng)網(wǎng)絡(luò)且具有比傳統(tǒng)ISA 更高的代碼密度和性能.然而,該指令集并不專用于CNN,為了通用性犧牲了部分CNN 特定的數(shù)據(jù)復(fù)用和指令中的并行計(jì)算.針對(duì)CNN應(yīng)用,Luca 等人[15,16]提出了PULP,一種可擴(kuò)展的多核計(jì)算平臺(tái),并在其中增加了硬件卷積引擎以加速卷積操作.該平臺(tái)中的單個(gè)核心均基于RISC-V 開(kāi)源架構(gòu),并擴(kuò)展了點(diǎn)積和packed-SIMD 等指令,可直接使用指令驅(qū)動(dòng)加速單元,節(jié)省了操作系統(tǒng)層面的開(kāi)銷.但是該團(tuán)隊(duì)并未針對(duì)網(wǎng)絡(luò)中的其他層設(shè)計(jì)相應(yīng)指令.因此,一個(gè)高效、靈活且易于實(shí)現(xiàn)的CNN 專用指令集仍是需要的.
本文通過(guò)研究典型的CNN 模型的計(jì)算模式提出了一個(gè)小型且易于實(shí)現(xiàn)的CNN 專用指令集,稱為RVCNN[17],其包含10 條矩陣指令,可以靈活地支持多種CNN 結(jié)構(gòu)的推理過(guò)程.隨后介紹了由CNN 模型描述文件到專用指令的映射過(guò)程.在實(shí)現(xiàn)方面,本文將指令集擴(kuò)展進(jìn)RISC-V 架構(gòu)處理器中,并對(duì)指令的實(shí)現(xiàn)進(jìn)行了特定的優(yōu)化.最終,通過(guò)典型的案例研究,本文從代碼密度、性能和能效方面對(duì)該指令集及其實(shí)現(xiàn)進(jìn)行了對(duì)比評(píng)估.
本文第1 節(jié)介紹專用指令集的設(shè)計(jì)偏好.第2 節(jié)詳細(xì)闡述專用指令的格式、功能以及代碼的映射過(guò)程,并展示部分代碼樣例.第3 節(jié)將指令集與典型專用指令集作定性比較.第4 節(jié)介紹基于RISC-V 核的指令集硬件實(shí)現(xiàn).第5 節(jié)展示實(shí)驗(yàn)步驟與實(shí)驗(yàn)結(jié)果.第6 節(jié)總結(jié)并介紹下一步工作.
本節(jié)主要展示了為設(shè)計(jì)一個(gè)高效且易于實(shí)現(xiàn)的CNN 專用指令集時(shí)的一些偏好,基于這些偏好,我們才能設(shè)計(jì)出具體的指令.
RISC-V 擴(kuò)展.以往CNN 硬件加速器通常以外設(shè)的方式工作,主機(jī)端通過(guò)驅(qū)動(dòng)對(duì)加速器進(jìn)行讀寫.考慮到大量數(shù)據(jù)在用戶空間與內(nèi)核空間的拷貝,這一過(guò)程中操作系統(tǒng)層面的時(shí)間以及資源開(kāi)銷顯然是不可避免的.然而,RISC-V 架構(gòu)的出現(xiàn)給加速器的工作模式帶來(lái)了更多選擇.該指令集架構(gòu)由基礎(chǔ)指令集和其他可選指令集組成,具有開(kāi)源性和指令可定制性,為用戶提供了定制處理器微架構(gòu)的可能[18]與設(shè)計(jì)專用指令的空間.因此,基于RISC-V 架構(gòu)設(shè)計(jì)專用指令控制加速單元的執(zhí)行也更簡(jiǎn)潔、更高效.基于以上兩點(diǎn)分析,我們最終選擇RISC-V作為目標(biāo)ISA,并在保持基本內(nèi)核和每個(gè)標(biāo)準(zhǔn)擴(kuò)展不變的前提下使用CNN 專用指令對(duì)其進(jìn)行擴(kuò)展.最終專用指令可以配合RV32 具有的標(biāo)量和邏輯控制指令完成CNN 的推理過(guò)程.
數(shù)據(jù)級(jí)并行.設(shè)計(jì)CNN 專用指令集涉及很多因素,但其中涉及性能瓶頸部分才是應(yīng)該關(guān)注的重點(diǎn).考慮到CNN 逐層堆疊的拓?fù)浣Y(jié)構(gòu)和不同層權(quán)重?cái)?shù)據(jù)的獨(dú)立性,設(shè)計(jì)矩陣指令以利用其操作中的數(shù)據(jù)級(jí)并行性而非挖掘其指令級(jí)并行性是更有效的.研究表明,在Intel Xeon 處理器核中用于計(jì)算的消耗僅占整個(gè)核能量消耗的37%[19],其余的能量消耗為體系結(jié)構(gòu)成本,并不是計(jì)算必須的.因此,在設(shè)計(jì)專用指令時(shí),增加指令的粒度,將指令取指、譯碼和控制的開(kāi)銷平攤到多個(gè)元素的計(jì)算上,可以有效提升執(zhí)行效率.此外,當(dāng)處理涉及大量數(shù)據(jù)的計(jì)算時(shí),與傳統(tǒng)的標(biāo)量指令相比,矩陣指令可以顯式地指定數(shù)據(jù)塊之間的獨(dú)立性,減少數(shù)據(jù)依賴檢測(cè)邏輯的大小.并且,矩陣指令還具有較高的代碼密度,因此我們這里主要關(guān)注數(shù)據(jù)級(jí)并行.
便簽存儲(chǔ)器(scratchpad memory).向量寄存器組通常出現(xiàn)在向量體系結(jié)構(gòu)中,其中,每個(gè)向量寄存器都包含了一個(gè)長(zhǎng)度固定的向量,并且允許處理器一次操作向量中的所有元素.便簽存儲(chǔ)器是在片上用于存儲(chǔ)臨時(shí)計(jì)算數(shù)據(jù)的高速內(nèi)部存儲(chǔ)器,其具有直接尋址訪問(wèn)、代價(jià)低以及可變長(zhǎng)度數(shù)據(jù)訪問(wèn)的特性.由于實(shí)現(xiàn)便簽存儲(chǔ)器的代價(jià)較低,因此通常部署較大尺寸的便簽存儲(chǔ)器并集成直接內(nèi)存訪問(wèn)(DMA)控制器,以便進(jìn)行快速的數(shù)據(jù)傳輸.此外,考慮到密集、連續(xù)、可變長(zhǎng)度的數(shù)據(jù)訪問(wèn)經(jīng)常發(fā)生在CNN 中,我們這里選擇使用便簽存儲(chǔ)器來(lái)替代傳統(tǒng)的向量寄存器組.
本節(jié)中,我們首先展示了專用指令集的構(gòu)成,然后詳細(xì)介紹了在第1 節(jié)中提出的設(shè)計(jì)偏好下專用指令的功能和格式.在此基礎(chǔ)上,我們介紹了從基于深度學(xué)習(xí)框架的CNN 模型描述文件到專用指令的映射過(guò)程,并列舉了由專用指令實(shí)現(xiàn)的卷積層和池化層的代碼.
RV-CNN 指令集的構(gòu)成見(jiàn)表1,其包含了數(shù)據(jù)傳輸指令、邏輯指令和計(jì)算指令.配合部分基礎(chǔ)的RV-32I 指令集(這里不再描述),該指令集可以完成典型的CNN 類計(jì)算.RV-CNN 指令集架構(gòu)仍然和RISC-V 架構(gòu)保持一致,屬于load-store 架構(gòu),僅通過(guò)專用的指令進(jìn)行數(shù)據(jù)傳輸.并且,該指令集仍使用RV-32 中的32 個(gè)32 位通用寄存器,用于存儲(chǔ)標(biāo)量值以及便簽存儲(chǔ)器的寄存器間接尋址.另外,我們?cè)O(shè)置了一個(gè)向量長(zhǎng)度寄存器(vector-length register,簡(jiǎn)稱VLR)來(lái)指定運(yùn)行時(shí)實(shí)際處理的向量長(zhǎng)度.下面對(duì)指令進(jìn)行詳細(xì)介紹.
Table 1 An overview of RV-CNN表1 RV-CNN 指令集綜述
2.1.1 數(shù)據(jù)傳輸指令
為了靈活地支持矩陣運(yùn)算,數(shù)據(jù)傳輸指令可以完成片外主存儲(chǔ)器和片上便簽存儲(chǔ)器之間可變大小的數(shù)據(jù)塊傳輸.圖1 展示了矩陣加載指令(MLOAD)的格式.
Fig.1 Matrix load (MLOAD)instruction format圖1 矩陣加載指令格式
圖1 中,Reg0 指定片上目標(biāo)地址.Reg1、Reg2 和Reg3 分別指定矩陣的源地址、矩陣的大小和相鄰元素的跨度.具體而言,該指令完成數(shù)據(jù)從主存向便簽存儲(chǔ)器的傳輸,其中,指令的步幅字段可以指定相鄰元素的跨度,從而避免了內(nèi)存中“昂貴的”矩陣轉(zhuǎn)置操作.相對(duì)應(yīng)地,矩陣存儲(chǔ)指令(MSTORE)完成便簽存儲(chǔ)器向主存儲(chǔ)器方向的數(shù)據(jù)傳輸,其指令格式與MLOAD 相似,不過(guò)經(jīng)常會(huì)忽略步幅字段以避免不連續(xù)的片外訪存.
2.1.2 矩陣計(jì)算指令
CNN 主要由卷積層、激勵(lì)層、池化層和全連接層組成,其中大部分計(jì)算都集中在卷積層[20].在卷積層的計(jì)算中,卷積核在輸入特征圖上連續(xù)移動(dòng),并在重合區(qū)域執(zhí)行點(diǎn)積以生成下一層的輸入數(shù)據(jù).在此過(guò)程中,同一卷積核在特征圖的不同區(qū)域之間的計(jì)算是獨(dú)立的,不同卷積核在特征圖的相同區(qū)域的計(jì)算也是獨(dú)立的.為了充分利用卷積計(jì)算中的并行性,我們采用Im2col(image to column)算法將2-D 卷積運(yùn)算轉(zhuǎn)換為矩陣乘法運(yùn)算(算法示意如圖2 所示).
Fig.2 Matrix multiplication version of convolution圖2 卷積運(yùn)算的矩陣乘法版本
將2-D 卷積映射到矩陣乘法操作后,可以很自然地使用MMM(matrix-multiply-matrix)指令執(zhí)行該操作.其指令格式如圖3 所示,其中,Reg0 指定矩陣輸出的便簽存儲(chǔ)器中的目的地址;16~12 位是指令的功能字段,指示矩陣乘運(yùn)算.Reg1 和Reg2 分別指定矩陣1 和矩陣2 的在便簽存儲(chǔ)器中的源地址.Reg3 中的4 個(gè)字節(jié)分別代表矩陣的高(H)、寬(W)、卷積核大小(K)、卷積步長(zhǎng)(S).考慮到實(shí)際執(zhí)行中分片技術(shù)的使用,這里使用單個(gè)字節(jié)存儲(chǔ)相應(yīng)的信息是足夠的.因此,卷積操作執(zhí)行時(shí)的參數(shù)信息被打包成32’b{H,W,K,S},并由Reg3 指定.同時(shí),由于數(shù)據(jù)分片載入,其產(chǎn)生的中間結(jié)果往往需要累加.這里不設(shè)置特定的矩陣加法指令而是設(shè)計(jì)了MMS 指令.該指令在完成矩陣乘法計(jì)算后,將部分結(jié)果寫入目標(biāo)地址時(shí)與該地址原有的值累加后再存儲(chǔ),使得在完成累加的同時(shí)減少數(shù)據(jù)的重新載入.該指令的格式和各字段含義均與MMM 指令一致,由功能字段指定該指令,故不再展示.此外,為了更大程度地利用數(shù)據(jù)局部性并減少對(duì)同一地址的并發(fā)讀/寫請(qǐng)求,我們選擇采用專用的MMM 指令執(zhí)行矩陣乘法,而不是將其分解為更細(xì)粒度的指令(例如,矩陣向量乘和矢量點(diǎn)積).
Fig.3 Matrix multiply matirx (MMM)instruction format圖3 矩陣乘矩陣指令格式
全連接層通常在整個(gè)卷積神經(jīng)網(wǎng)絡(luò)的尾部以對(duì)之前各層學(xué)得的特征進(jìn)行映射達(dá)到分類效果.全連接層的計(jì)算可以用矩陣向量乘法表示,而MMM 指令在不同的參數(shù)下同樣可以表示全連接層的計(jì)算,因此卷積層和全連接層可以復(fù)用相同的計(jì)算單元.
2.1.3 矩陣邏輯指令
融合(fusion)[21]作為目前DNN 加速器設(shè)計(jì)中常用的技術(shù),通過(guò)將部分層加以融合,從而以一次數(shù)據(jù)的加載、存儲(chǔ)替代單獨(dú)層的數(shù)據(jù)輸入輸出操作來(lái)最小化帶寬限制.融合操作的優(yōu)勢(shì)以及目前CNN 中激活層通常緊接在卷積層或全連接層之后的特點(diǎn),使得設(shè)計(jì)相應(yīng)的粗粒度指令將兩者融合執(zhí)行是非常適合的.而且激勵(lì)層不改變輸入張量的尺寸且激活函數(shù)逐元素進(jìn)行激活操作,其需要的參數(shù)較少.因此,我們?cè)O(shè)計(jì)了MMMA 指令,使矩陣相乘得到卷積層或全連接層的部分最終結(jié)果后可經(jīng)過(guò)激活操作后輸出,其指令格式與各字段含義均和MMM 指令一致,由功能字段指定該指令.不過(guò),我們?nèi)匀槐A袅思せ钪噶?以完成對(duì)輸入的數(shù)據(jù)進(jìn)行激活操作,其指令格式如圖4 所示,其指令中的31~27 位用來(lái)決定激活函數(shù)的選擇,如ReLU()/sigmoid()/Tanh().
Fig.4 Matrix activation (MACT)instruction format圖4 矩陣激活指令格式
池化層通過(guò)降采樣將輸入數(shù)據(jù)的每個(gè)窗口子采樣到單個(gè)池輸出以減小輸入圖片的尺寸.實(shí)際上,卷積神經(jīng)網(wǎng)絡(luò)中相較于卷積層和全連接層,其余層包含了很少的計(jì)算且被數(shù)據(jù)訪問(wèn)時(shí)間限制.在某些CNN 模型中,對(duì)池化層和相鄰層采用融合技術(shù)同樣是有效的.但是,不同于激活層在CNN 中的位置相對(duì)固定且按元素操作,池化層仍具有一定的靈活度,如3 個(gè)卷積層堆疊后池化.于是,這里我們?nèi)詫⒊鼗瘜赢?dāng)作單獨(dú)的層來(lái)處理.用于進(jìn)行最大值池化的MXPOOL 的指令格式如圖5 所示.其中,Reg0、Reg1、Reg2 分別表示輸出數(shù)據(jù)的目標(biāo)地址、輸入數(shù)據(jù)的源地址和輸入數(shù)據(jù)的長(zhǎng)度.借鑒設(shè)計(jì)MMM 指令的思想,觀察到池化窗口通常為2×2、3×3、5×5 等小尺寸而且通常采用分片技術(shù)處理輸入數(shù)據(jù),所以使用單個(gè)字節(jié)分別表示一次分片可處理的輸入矩陣的高(H)、寬(W)、池化窗口大小(K)和步長(zhǎng)(S)是足夠的.這些必要信息進(jìn)而被打包為32 位值,由Reg3 指定.
Fig.5 Matrix maximum (MXPOOL)instruction format圖5 矩陣池化指令格式
RV-CNN 指令生成流程如圖6 所示.其中,CNN 模型描述文件可以是深度學(xué)習(xí)工程師熟悉的Caffe、TensorFlow 或Pytorch 等流行框架下的描述文件.由模型分析器對(duì)該描述文件進(jìn)行解析以生成用于模型構(gòu)建的參數(shù)信息和重排后的權(quán)重信息.在此基礎(chǔ)上,應(yīng)根據(jù)網(wǎng)絡(luò)參數(shù)信息構(gòu)建數(shù)據(jù)流圖并提取算子,然后在不同的融合策略下將提取出的算子映射至指令池(RV-CNN 指令集)中的不同指令.由于我們?cè)O(shè)計(jì)的指令均為粗粒度指令,這里應(yīng)提取粒度適合的算子才能映射至目標(biāo)指令集.在專用指令提取后,應(yīng)根據(jù)硬件的參數(shù)信息,如片上便簽存儲(chǔ)器的大小和硬件計(jì)算資源規(guī)模來(lái)決定分片大小.同時(shí)根據(jù)復(fù)用策略,如輸入復(fù)用或權(quán)值復(fù)用等對(duì)指令進(jìn)行編排以生成最終的代碼.其中,應(yīng)使用RV32 基礎(chǔ)指令集將參數(shù)信息加載至寄存器并完成循環(huán)控制.
Fig.6 RV-CNN instructions generation process圖6 RV-CNN 指令生成流程
為了闡述提出的專用指令集的用法,我們列舉了使用RV-CNN 構(gòu)建的CNN 中兩個(gè)具有代表性的部分,即卷積層和池化層.其中,卷積層的實(shí)現(xiàn)通過(guò)融合指令包含了激勵(lì)層的操作.而全連接層的代碼實(shí)現(xiàn)與卷積層代碼類似,僅在配置參數(shù)上略有不同,故不作列舉.
2.3.1 卷積層代碼示例
RV-CNN 實(shí)現(xiàn)的卷積層代碼如圖7 所示,其中,左側(cè)是在Caffe 框架中編寫的卷積層代碼(用以示意),其完成對(duì)輸入特征圖(14×14×512),使用512 組尺寸為3×3、步幅為1 的卷積核進(jìn)行特征提取的過(guò)程.圖中右側(cè)則是使用專用指令完成相同功能的示意代碼,其中假設(shè)硬件片上資源充足且數(shù)據(jù)排列順序合適.
由于指令從寄存器中獲取參數(shù)信息,因此我們首先需要向寄存器中加載必要的信息.這里首先加載立即數(shù)0×0E0E0301 至$5 寄存器,根據(jù)第2 節(jié)對(duì)指令格式的描述,該32 位數(shù)據(jù)中由高至低的4 個(gè)字節(jié)分別代表了輸入數(shù)據(jù)的高度(14)、寬度(14)、卷積核尺寸(3)以及步幅(1).之后設(shè)置向量寄存器VLR 為16,代表一次處理的向量長(zhǎng)度為16.由于采用分片技術(shù),這里設(shè)置循環(huán)計(jì)數(shù)器$11、$12 來(lái)完成深度方向和不同卷積核的遍歷.隨后,通過(guò)在寄存器$6、$8、$10 中加載數(shù)據(jù)在片外DDR 中的實(shí)際地址,以便通過(guò)MLOAD/MSTORE 完成數(shù)據(jù)傳輸.以上寄存器中的信息應(yīng)由指令生成器或者用戶根據(jù)網(wǎng)絡(luò)模型以及硬件參數(shù)信息生成.在此基礎(chǔ)上,開(kāi)始實(shí)際計(jì)算過(guò)程.首先分別將數(shù)據(jù)從片外0×30000 和0×50000 處加載至由$1 和$2 指定的片上目的地址.數(shù)據(jù)加載完畢后,通過(guò)執(zhí)行MMM 指令完成計(jì)算.計(jì)算過(guò)程中的中間結(jié)果保存在片上便簽存儲(chǔ)器中.之后的計(jì)算通過(guò)使用MMMS 指令完成計(jì)算與片上中間結(jié)果累加,以減少不必要的片外訪存.最終,通過(guò)執(zhí)行MMMSA 指令完成部分最終結(jié)果的激活,并由MSTORE 指令將結(jié)果傳輸至片外.
Fig.7 Convolutional layer code example implemented by RV-CNN圖7 RV-CNN 實(shí)現(xiàn)的卷積層代碼示例
2.3.2 池化層代碼示例
RV-CNN 實(shí)現(xiàn)的池化層代碼如圖8 所示,左側(cè)仍以Caffe 框架中編寫池化層代碼作功能示意,其表示對(duì)輸入特征圖(14×14×512),使用2×2、步幅為2 的池化窗口進(jìn)行最大值采樣.圖右側(cè)則是使用專用指令完成相同功能的示意代碼,其中仍假設(shè)硬件片上資源充足且數(shù)據(jù)排列順序合適.
由于池化層不包含權(quán)重?cái)?shù)據(jù)且不在深度方向上累積,在輸入圖片大小合適的情況下,其RV-CNN 實(shí)現(xiàn)的代碼比卷積層代碼要簡(jiǎn)潔.在向相應(yīng)寄存器中加載完參數(shù)后,利用MLOAD 指令將待處理數(shù)據(jù)從片外0×10000($6)處加載至片上目的地址$1 處.輸入數(shù)據(jù)加載完畢后,使用MXPOOL 指令進(jìn)行降采樣并將結(jié)果存儲(chǔ)在片上臨時(shí)地址$5 處,采樣結(jié)束后,則由MSTORE 將結(jié)果傳輸至片外地址0×40000($7)處,該過(guò)程中輸出并不會(huì)在片上累加.代碼中的循環(huán)計(jì)數(shù)器是為了在輸入數(shù)據(jù)深度方向上遍歷,一次載入、池化、載出完成一次分片數(shù)據(jù)的采樣,之后更新載入、載出地址以及計(jì)數(shù)器值.
Fig.8 Pooling layer code example implemented by RV-CNN圖8 RV-CNN 實(shí)現(xiàn)的池化層代碼示例
目前,在面向神經(jīng)網(wǎng)絡(luò)領(lǐng)域的專用指令集中,Cambricon 指令集被認(rèn)為是最具代表性的指令集之一,而基于RISC-V 架構(gòu)的向量指令集擴(kuò)展(RV-V)也被認(rèn)為是加速神經(jīng)網(wǎng)絡(luò)計(jì)算的指令集.因此,本節(jié)將圍繞指令集的適用范圍、粗細(xì)粒度以及映射機(jī)制等方面,將RV-CNN 與以上兩種典型指令集進(jìn)行定性分析和對(duì)比.
適用范圍.RV-V 指令集的建立旨在利用應(yīng)用中的數(shù)據(jù)級(jí)并行,其可廣泛應(yīng)用于科學(xué)計(jì)算、數(shù)據(jù)信號(hào)處理以及機(jī)器學(xué)習(xí)等領(lǐng)域.Cambricon 指令集則是面向神經(jīng)網(wǎng)絡(luò)領(lǐng)域,如CNN、循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)以及長(zhǎng)短期記憶網(wǎng)絡(luò)(LSTM)等10 余種網(wǎng)絡(luò)模型而設(shè)計(jì)的指令集.相比之下,RV-CNN 指令集著重針對(duì)神經(jīng)網(wǎng)絡(luò)領(lǐng)域中的CNN 而設(shè)計(jì),其中涉及的運(yùn)算類型較少.因此,前兩者針對(duì)的領(lǐng)域更廣泛,設(shè)計(jì)的難度也更大,這在指令集包含的指令類型和數(shù)目上也有所體現(xiàn).RV-V 指令集已經(jīng)包含了超過(guò)60 條指令(草稿版本0.8),Cambricon 指令集中包含了47條指令,而RV-CNN 指令集僅包含了10 條指令.
粗細(xì)粒度.RV-V 和RV-CNN 指令集中分別包含了向量和矩陣指令,而Cambricon 指令集中則包含了標(biāo)量、向量以及矩陣3 類不同的指令.Cambricon 之所以包含標(biāo)量指令是因?yàn)槠湓诟拍钌鲜且粋€(gè)完備的神經(jīng)網(wǎng)絡(luò)指令集,但其中用于加速計(jì)算的仍是向量和矩陣指令.因此,在指令粒度層面上,RV-CNN 指令集是三者中指令粒度最大的,Cambricon 指令集其次,由于RV-V 指令集中均是向量指令,相比之下粒度最小.這也與指令集的適用范圍相關(guān),由于在設(shè)計(jì)RV-V 指令集時(shí)針對(duì)的應(yīng)用領(lǐng)域最為廣泛,因此需要從多種計(jì)算操作中提取共性部分.考慮到硬件規(guī)模及能耗限制,這一過(guò)程往往需要結(jié)合算法特性,將不同的計(jì)算過(guò)程不斷地向下拆分以尋求計(jì)算共性,提高指令集的表達(dá)能力,因此相較于前兩者RV-V 指令集的指令粒度最小.
代碼映射機(jī)制.Cambricon 指令集的代碼映射是基于框架的,其為流行的編程框架提供適配的機(jī)器學(xué)習(xí)高性能庫(kù)與軟件運(yùn)行時(shí)支持,向上為框架提供豐富的算子和計(jì)算圖方法以構(gòu)造整個(gè)網(wǎng)絡(luò),向下通過(guò)調(diào)用內(nèi)置驅(qū)動(dòng)產(chǎn)生指令以控制硬件.RV-CNN 指令集的代碼映射過(guò)程以基于框架的模型描述文件開(kāi)始,不同于Cambricon 對(duì)框架進(jìn)行修改,RV-CNN 僅對(duì)框架下的模型描述文件進(jìn)行分析,從而提取模型結(jié)構(gòu)及權(quán)重信息,進(jìn)而配合融合策略建立模型中算子和指令間的映射關(guān)系,之后根據(jù)復(fù)用策略進(jìn)行指令編排,最終經(jīng)匯編形成可執(zhí)行文件.RV-V 指令集目前處于正在進(jìn)行的狀態(tài),還未提供可使用的編譯器來(lái)完成對(duì)代碼的自動(dòng)矢量化過(guò)程,仍需要用戶手寫匯編指令.但其中涉及到大量細(xì)粒度的向量指令,這給編程過(guò)程中寄存器分配以及指令編排增加了難度.
本節(jié)首先介紹了包含RV-CNN 指令擴(kuò)展的開(kāi)源處理器核的整體結(jié)構(gòu),并詳細(xì)介紹了指令的執(zhí)行流程.隨后講述了與RV-CNN 指令相對(duì)應(yīng)的矩陣單元的組成及其子單元的功能,其中詳細(xì)展示了矩陣乘法單元的結(jié)構(gòu),最后介紹了有關(guān)矩陣單元的優(yōu)化細(xì)節(jié).
包含了RV-CNN 擴(kuò)展的RISC-V 處理器核的主要功能部件以及簡(jiǎn)化的流水線結(jié)構(gòu)如圖9 所示.可見(jiàn),其包含了基本的5 個(gè)流水線階段:取指、譯碼、執(zhí)行、訪存和寫回.其中,矩陣計(jì)算單元處于流水線的執(zhí)行階段,用于完成矩陣指令的執(zhí)行.在取指、譯碼階段之后,基礎(chǔ)指令集中的指令將進(jìn)入ALU,然后進(jìn)入下一個(gè)階段.當(dāng)譯碼階段解析出當(dāng)前指令是矩陣指令后,譯碼器從寄存器中獲得相應(yīng)信息并保存,待下一個(gè)周期送入矩陣單元.矩陣單元根據(jù)接受的指令信息并檢測(cè)相應(yīng)功能部件的狀態(tài)以確定是否執(zhí)行.由于片上便簽寄存器的地址空間用戶可見(jiàn),矩陣單元可以通過(guò)矩陣數(shù)據(jù)傳輸指令和內(nèi)存進(jìn)行交互,因此,矩陣指令進(jìn)入矩陣單元后不會(huì)經(jīng)過(guò)訪存和寫回兩個(gè)階段,而其余指令不通過(guò)矩陣單元,其訪存仍通過(guò)高速緩存(cache).這樣可以避免不必要的數(shù)據(jù)依賴性檢測(cè)和硬件自動(dòng)的數(shù)據(jù)換入換出.此外,由于矩陣單元包含了大量的計(jì)算單元,其內(nèi)部有自己的流水線結(jié)構(gòu),譯碼器根據(jù)矩陣單元能否接受矩陣指令信息來(lái)決定是否停止流水線.鑒于矩陣指令連續(xù)、大量的數(shù)據(jù)訪問(wèn),我們?cè)诒愫灤鎯?chǔ)器外集成了DMA 控制器,以便滿足矩陣單元的數(shù)據(jù)訪問(wèn)需求.需要注意的是,矩陣單元完成計(jì)算和邏輯類指令所涉及的數(shù)據(jù)需要已經(jīng)存在于片上,這需要程序的嚴(yán)格控制.
Fig.9 A simplified block diagram of processor core with RV-CNN extension圖9 包含RV-CNN 擴(kuò)展的處理器核簡(jiǎn)化框圖
矩陣單元的整體結(jié)構(gòu)如圖10 所示,其內(nèi)部主要包含了輸入輸出單元、矩陣乘法單元、激活單元、池化單元以及內(nèi)部控制器,其中,橙色和灰色箭頭分別表示控制流和數(shù)據(jù)流.矩陣單元接收傳入的指令信息以及寄存器信息后存儲(chǔ)到隊(duì)列中.內(nèi)部控制器(作為有限狀態(tài)機(jī))是矩陣單元的控制中心,其根據(jù)控制信息將喚醒子組件(如果可用)以完成相應(yīng)任務(wù).否則,它將生成一個(gè)反饋信號(hào)以指示相應(yīng)的功能單元正忙.緩沖模塊本質(zhì)上是一個(gè)片上存儲(chǔ)器,矩陣單元中的計(jì)算核心從中獲取數(shù)據(jù)并將產(chǎn)生的結(jié)果寫入.除融合指令會(huì)同時(shí)啟動(dòng)多個(gè)計(jì)算核心外,計(jì)算單元大致上與粗粒度指令一一對(duì)應(yīng).最后,輸入輸出模塊則負(fù)責(zé)根據(jù)有效地址在矩陣單元與片上便簽存儲(chǔ)器之間進(jìn)行數(shù)據(jù)傳輸.
由于矩陣乘法單元被卷積層和全連接層共用,其承擔(dān)了大部分計(jì)算,因此該單元的實(shí)現(xiàn)對(duì)性能至關(guān)重要.這里我們采用了脈動(dòng)陣列結(jié)構(gòu)實(shí)現(xiàn)的矩陣乘法,其結(jié)構(gòu)如圖10 右側(cè)部分所示.脈動(dòng)陣列是一種高效且簡(jiǎn)單的矩陣乘法實(shí)現(xiàn)方式,其通過(guò)二維網(wǎng)格將MAC(multiply-accumulate)單元綁定在一起,除陣列的最外側(cè)層(這里是最左側(cè)和最上側(cè))的計(jì)算單元直接與片上緩沖相連以獲取數(shù)據(jù)外,其余計(jì)算單元均從其鄰居中獲得輸入.這種方式在MAC 陣列規(guī)模變大時(shí)將顯著減少片上緩沖的扇入扇出.同時(shí),數(shù)據(jù)在MAC 單元之間流動(dòng)性地傳遞也增加了數(shù)據(jù)復(fù)用.例如,當(dāng)MAC 陣列為12×16 時(shí),矩陣B中的元素按行在不同時(shí)刻由左至右在陣列中傳遞,數(shù)據(jù)輸出時(shí)復(fù)用了16 次;類似地,矩陣A中的元素按列在不同時(shí)刻由上至下在陣列中傳遞,輸出時(shí)復(fù)用了12 次.在這一過(guò)程中,配合流水線優(yōu)化,每周期只需要向陣列輸入28 個(gè)數(shù),就可以進(jìn)行192 個(gè)MAC 操作.此外,短的局部互連也降低了布局布線的難度,因此,這里我們選擇使用脈動(dòng)陣列作為矩陣乘法的實(shí)現(xiàn)方式.
Fig.10 The block diagram of the matrix unit圖10 矩陣單元的結(jié)構(gòu)示意圖
數(shù)據(jù)復(fù)用.在處理卷積層時(shí),對(duì)輸入數(shù)據(jù)進(jìn)行Im2col 操作將在內(nèi)存占用和帶寬方面帶來(lái)不菲的開(kāi)銷.例如,當(dāng)卷積核步幅為1 時(shí),與原始輸入數(shù)據(jù)相比,轉(zhuǎn)換后的輸入矩陣消耗的內(nèi)存約為原始的K×K倍.為了保留Im2col操作帶來(lái)的好處,同時(shí)減少額外的開(kāi)銷,我們實(shí)現(xiàn)了片上Im2col 緩沖區(qū),并根據(jù)地址在片上對(duì)切片數(shù)據(jù)進(jìn)行數(shù)據(jù)重排和展開(kāi).設(shè)置Im2col 緩沖區(qū)可以有效地增加數(shù)據(jù)復(fù)用,雖然并未減少輸入數(shù)據(jù)的訪問(wèn)次數(shù),但使用開(kāi)銷較小的片上訪問(wèn)代替了開(kāi)銷大的片外訪問(wèn),從而大大減少了該操作造成的額外的數(shù)據(jù)訪問(wèn)開(kāi)銷和外部帶寬壓力.
數(shù)據(jù)量化.傳統(tǒng)上,無(wú)論是CNN 的訓(xùn)練階段還是預(yù)測(cè)階段,其數(shù)據(jù)類型均采用32 位單精度浮點(diǎn)數(shù),這主要是因?yàn)樗乾F(xiàn)代GPU 的標(biāo)準(zhǔn)數(shù)據(jù)格式.但研究發(fā)現(xiàn),CNN 對(duì)有限的數(shù)值精度具有固有的魯棒性,在預(yù)測(cè)階段使用浮點(diǎn)計(jì)算并不是必須的.通過(guò)重訓(xùn)練和特定的微調(diào)手段,采用定點(diǎn)數(shù)進(jìn)行預(yù)測(cè)造成的精度損失可以忽略不計(jì)(小于1%)[22].對(duì)于許多CNN 來(lái)說(shuō),甚至8 位位寬就可以達(dá)到足夠的精度.之所以采取量化操作,是因?yàn)闄?quán)重和激活的低位寬表示形式有助于避免昂貴的浮點(diǎn)計(jì)算,同時(shí)顯著減少帶寬需求和內(nèi)存占用.DianNao[11]中顯示,在臺(tái)積電65nm 工藝條件下,實(shí)現(xiàn)32 位乘法器的面積和功耗要比16 位乘法器的功耗高一個(gè)數(shù)量級(jí).在這種權(quán)衡之下,本文中矩陣單元的所有計(jì)算核心均采用16 位定點(diǎn)數(shù).
為了驗(yàn)證所提出的專用指令的有效性,我們?cè)贔PGA 平臺(tái)上構(gòu)建了包含該指令集擴(kuò)展的基于RISC-V 架構(gòu)的處理器核.在此基礎(chǔ)上,使用AlexNet、VGG16 兩種不同規(guī)模的卷積神經(jīng)網(wǎng)絡(luò)進(jìn)行評(píng)測(cè),并將該原型系統(tǒng)與Cambricon、CPU、GPU 和其他FPGA 加速器進(jìn)行對(duì)比分析.
(1)原型系統(tǒng)的FPGA 實(shí)現(xiàn)
我們使用ZC702 開(kāi)發(fā)板作為實(shí)驗(yàn)平臺(tái),該平臺(tái)為嵌入式FPGA 平臺(tái),其中,包含了一塊XC7Z020 FPGA 芯片和1GB DDR3 板載內(nèi)存,可提供4.2GB/s 的片外數(shù)據(jù)存取帶寬.RISC-V 基礎(chǔ)內(nèi)核及矩陣單元的控制使用硬件描述語(yǔ)言Verilog 來(lái)完成,矩陣單元中的子計(jì)算單元設(shè)計(jì)則通過(guò)Xilinx Vivado HLS 2017.4 高層次綜合工具完成,完整的硬件工程通過(guò)Xilinx Vivado 2017.4 集成開(kāi)發(fā)環(huán)境進(jìn)行綜合和實(shí)現(xiàn).
(2)CPU 測(cè)試基準(zhǔn)
我們使用Caffe 深度學(xué)習(xí)框架(CPU-only)在CPU 平臺(tái)上部署了兩種目標(biāo)網(wǎng)絡(luò)模型.CPU 配置為Intel i7-4790K,其中包含了4 物理核心,最大線程數(shù)為8,工作頻率為4GHz,并配有16GB DDR3 內(nèi)存.
(3)GPU 測(cè)試基準(zhǔn)
GPU 版本的測(cè)試仍然通過(guò)Caffe 深度學(xué)習(xí)框架(GPU-only)并通過(guò)CuDNN5.1 加速庫(kù)在GPU 平臺(tái)上部署兩種目標(biāo)網(wǎng)絡(luò)模型.GPU 配置為NVIDIA Tesla K40C,其最大可支持2 880 個(gè)硬件線程,工作頻率為745~875MHz,并配有12GB GDDR5 顯存.
在本節(jié)中,我們首先報(bào)告了原型系統(tǒng)在FPGA 平臺(tái)上的資源消耗和功耗,然后圍繞代碼密度、性能及能效3個(gè)方面將該設(shè)計(jì)與Cambricon、CPU、GPU 以及以往基于FPGA 的加速器進(jìn)行對(duì)比分析.
通過(guò)查看原型系統(tǒng)在Vivado 工具中的部署報(bào)告,我們獲得了其在目標(biāo)平臺(tái)的各項(xiàng)資源消耗以及FPGA 的功耗,見(jiàn)表2.
(1)與Cambricon、CPU、GPU 平臺(tái)的代碼密度、性能及能效對(duì)比
代碼密度.本文提出的專用指令不僅適用于加速CNN 應(yīng)用,而且還為具有類似計(jì)算模式的其他深度學(xué)習(xí)算法(如MLPs)提供支持.通過(guò)使用RV-CNN、C 和CUDA-C 實(shí)現(xiàn)流行的CNN 模型并測(cè)量其代碼長(zhǎng)度,我們對(duì)比了RV-CNN 指令與基礎(chǔ)RV32、ARM、x86 和GPU 的代碼密度,結(jié)果如圖11 所示,其中,以RV-CNN 指令集實(shí)現(xiàn)的代碼長(zhǎng)度為基準(zhǔn).可見(jiàn),相比于原本的RV32(IMF)指令集,擴(kuò)展RV-CNN 后代碼長(zhǎng)度減少了10.10 倍.相比于GPU、x86 與ARM 指令集,RV-CNN 的代碼長(zhǎng)度分別減少了1.95 倍、8.91 倍和10.97 倍.以x86 指令的代碼長(zhǎng)度為基準(zhǔn),RV-CNN 的代碼長(zhǎng)度相比于Cambricon 減少了1.51 倍.
性能及能效.圖12 展示了在兩種神經(jīng)網(wǎng)絡(luò)(AlexNet 和VGG16)的推理過(guò)程測(cè)試下,該設(shè)計(jì)與CPU 和GPU的性能、能效對(duì)比,其中,所有數(shù)值均可歸一化到CPU 的實(shí)驗(yàn)結(jié)果上.可見(jiàn),在Xilinx ZC702 平臺(tái)上,該設(shè)計(jì)在執(zhí)行兩種網(wǎng)絡(luò)的性能上均優(yōu)于CPU,分別達(dá)到2.64 倍和4.23 倍的加速效果.但是由于該平臺(tái)是嵌入式平臺(tái),用于計(jì)算的硬件資源DSP(使用91%)成為主要的性能瓶頸,因此在執(zhí)行兩種網(wǎng)絡(luò)的性能上均落后于GPU.在能效方面,以每瓦特性能(GOPS/w)為基準(zhǔn),該設(shè)計(jì)在AlexNet 和VGG-16 的推理上,相較于CPU 分別提升了101.49 倍和167.62 倍;相較于GPU 分別提升了1.06 倍和1.40 倍.由于Cambricon 加速器為ASIC 設(shè)計(jì),因此我們這里對(duì)比了性能密度(op/multiplier/cycle),即每周期乘法器完成的操作數(shù).以GPU 的測(cè)試數(shù)據(jù)為基準(zhǔn),RV-CNN 相比于Cambricon 有1.16 倍的提升.
(2)與其他FPGA 加速器的對(duì)比
表3 列出了本設(shè)計(jì)與已有的典型FPGA 加速器的對(duì)比結(jié)果.由于不同的工作采用了不同的量化策略和不同的硬件進(jìn)行部署,因此很難選擇出一種有效且精確的比較方法.若以每秒千兆操作數(shù)(GOPS)作為性能評(píng)估標(biāo)準(zhǔn),以前的工作可以實(shí)現(xiàn)比我們更好的性能.但是,更高的性能背后是更多的資源消耗,例如DSP 和LUT 資源,因而功耗也會(huì)相應(yīng)增加.若以每瓦特的性能(GOPS/w)作為能效評(píng)估標(biāo)準(zhǔn),與以往的加速器相比,我們的設(shè)計(jì)在保持靈活性下仍具有較高的能效.
Fig.11 The reduction of code length against Cambricon,GPU,x86,RV32,and ARM圖11 RV-CNN 相對(duì)于Cambricon、GPU、x86、RV32 以及ARM 的代碼長(zhǎng)度減少
Fig.12 Performance and energy efficiency comparison between prototype system and CPU and GPU圖12 原型系統(tǒng)與CPU、GPU 的性能、能效對(duì)比
Table 3 Comparison of the prototype system and previous FPGA-based accelerator deployment表3 原型系統(tǒng)與以往基于FPGA 的加速器部署對(duì)比
CNN 在圖像識(shí)別、目標(biāo)檢測(cè)領(lǐng)域的廣泛應(yīng)用使其性能至關(guān)重要.本文通過(guò)分析典型CNN 的計(jì)算模式,提出了一種高效且易于實(shí)現(xiàn)的專用指令集RV-CNN,其包含了10 條粗粒度的矩陣指令,可以靈活地為典型CNN 模型推理過(guò)程提供支持.在此基礎(chǔ)上,我們介紹了CNN 模型描述文件到RV-CNN 指令的映射過(guò)程.隨后通過(guò)定性分析,從不同方面將RV-CNN 與典型專用指令集進(jìn)行比較.在指令實(shí)現(xiàn)方面,我們將該指令集擴(kuò)展進(jìn)了基于開(kāi)源架構(gòu)RISC-V 的處理器核,并以相對(duì)緊耦合的方式將對(duì)應(yīng)的矩陣單元嵌入經(jīng)典的5 級(jí)流水線中.最后,本設(shè)計(jì)在Xilinx ZC702 平臺(tái)對(duì)上進(jìn)行綜合實(shí)現(xiàn),并以典型的神經(jīng)網(wǎng)絡(luò)進(jìn)行測(cè)試.結(jié)果顯示,相比于Intel i7-4790K 處理器和Tesla k40c GPU,該原型系統(tǒng)具有最高的能效和代碼密度.此外,與先前的加速器相比,該原型系統(tǒng)在保持靈活性的同時(shí)也展現(xiàn)了不錯(cuò)的能效.
目前新型CNN 網(wǎng)絡(luò)層出不窮,還需考慮對(duì)其中諸如深度可分離卷積等操作進(jìn)行指令優(yōu)化以提高執(zhí)行效率.此外,擴(kuò)展指令的設(shè)計(jì)與實(shí)現(xiàn)應(yīng)針對(duì)RISC-V 特點(diǎn)做出協(xié)同優(yōu)化.最后,根據(jù)模型及硬件信息執(zhí)行的代碼映射過(guò)程還未自動(dòng)化,未來(lái),計(jì)劃在以上方面加以改進(jìn).