(中國科學技術大學 計算機科學與技術學院,安徽 合肥 230027)
作為現代人工智能的重要分支,人工神經網絡(artificial neural network,簡稱ANN)近年來得到迅速發展.深度學習作為其在大數據時代背景下的延續和進化,通過增加網絡模型的深度,有效增強了傳統ANN 算法的數據特征提取能力.其中,卷積神經網絡(CNN)作為深度學習中廣泛采用的算法,被人們實現在如人臉識別[1]、目標檢測[2]、語音識別[3]、自然語言理解[4]等應用中,并取得了令人矚目的成果.得益于其在各類應用場景中的出色表現,CNN 已成為研究人員關注的重點,并廣泛部署在數據中心以及邊緣嵌入式設備中.
然而,CNN 出色的識別精度背后是不斷加深、復雜的網絡結構和巨大的計算、訪存量.近年來,CNN 模型的參數量達到了百萬級別,計算量達到千兆級別[5-7].CNN 密集的計算和訪存也給通用處理器帶來了巨大的壓力.因此,近年來涌現了許多基于FPGA[8-10]、GPU[5]和ASIC[11,12]的加速器,并達到了優于CPU 的性能和能效.在這3 類平臺中,相比于動輒消耗數十瓦甚至數百瓦的GPU 平臺,FPGA 和ASIC 通常具有更低的功耗.盡管GPU 在CNN 模型的訓練階段具有獨特的優勢,但離線訓練以進行在線預測的模式使得模型推理過程更加關鍵.而在推理過程中,FPGA、ASIC 的低功耗特性使其具有更廣泛的應用領域,如電量受限的嵌入式平臺.因此本文主要關注基于這兩類平臺的CNN 加速器的相關工作.但經觀察發現,先前的工作中此類加速器通常僅加速特定的網絡結構或特定類型的層,模式相對固定,靈活性較低.
為了解決這一問題,陳云霽團隊提出了DianNao[11],一款針對不同機器學習應用的高吞吐量ASIC 芯片,并設計了超長指令字(very long instruction word,簡稱VLIW)風格的指令,其支持CNN 和多層感知機模型(multilayer perceptrons,簡稱MLPs).相繼提出的DaDianNao[13]則是在DianNao 基礎上的SIMD 實現,不同之處在于用于計算的權值矩陣固化到本地的eDRAM 上,減少了讀取內存的次數.但兩者中VLIW 風格指令對計算過程的抽象較差,若不了解底層硬件,則難以使用.隨后,該團隊通過對ANN 中的計算進行抽象,設計了專用指令集Cambricon[14],其包含了標量、向量和矩陣等指令,支持多種神經網絡且具有比傳統ISA 更高的代碼密度和性能.然而,該指令集并不專用于CNN,為了通用性犧牲了部分CNN 特定的數據復用和指令中的并行計算.針對CNN應用,Luca 等人[15,16]提出了PULP,一種可擴展的多核計算平臺,并在其中增加了硬件卷積引擎以加速卷積操作.該平臺中的單個核心均基于RISC-V 開源架構,并擴展了點積和packed-SIMD 等指令,可直接使用指令驅動加速單元,節省了操作系統層面的開銷.但是該團隊并未針對網絡中的其他層設計相應指令.因此,一個高效、靈活且易于實現的CNN 專用指令集仍是需要的.
本文通過研究典型的CNN 模型的計算模式提出了一個小型且易于實現的CNN 專用指令集,稱為RVCNN[17],其包含10 條矩陣指令,可以靈活地支持多種CNN 結構的推理過程.隨后介紹了由CNN 模型描述文件到專用指令的映射過程.在實現方面,本文將指令集擴展進RISC-V 架構處理器中,并對指令的實現進行了特定的優化.最終,通過典型的案例研究,本文從代碼密度、性能和能效方面對該指令集及其實現進行了對比評估.
本文第1 節介紹專用指令集的設計偏好.第2 節詳細闡述專用指令的格式、功能以及代碼的映射過程,并展示部分代碼樣例.第3 節將指令集與典型專用指令集作定性比較.第4 節介紹基于RISC-V 核的指令集硬件實現.第5 節展示實驗步驟與實驗結果.第6 節總結并介紹下一步工作.
本節主要展示了為設計一個高效且易于實現的CNN 專用指令集時的一些偏好,基于這些偏好,我們才能設計出具體的指令.
RISC-V 擴展.以往CNN 硬件加速器通常以外設的方式工作,主機端通過驅動對加速器進行讀寫.考慮到大量數據在用戶空間與內核空間的拷貝,這一過程中操作系統層面的時間以及資源開銷顯然是不可避免的.然而,RISC-V 架構的出現給加速器的工作模式帶來了更多選擇.該指令集架構由基礎指令集和其他可選指令集組成,具有開源性和指令可定制性,為用戶提供了定制處理器微架構的可能[18]與設計專用指令的空間.因此,基于RISC-V 架構設計專用指令控制加速單元的執行也更簡潔、更高效.基于以上兩點分析,我們最終選擇RISC-V作為目標ISA,并在保持基本內核和每個標準擴展不變的前提下使用CNN 專用指令對其進行擴展.最終專用指令可以配合RV32 具有的標量和邏輯控制指令完成CNN 的推理過程.
數據級并行.設計CNN 專用指令集涉及很多因素,但其中涉及性能瓶頸部分才是應該關注的重點.考慮到CNN 逐層堆疊的拓撲結構和不同層權重數據的獨立性,設計矩陣指令以利用其操作中的數據級并行性而非挖掘其指令級并行性是更有效的.研究表明,在Intel Xeon 處理器核中用于計算的消耗僅占整個核能量消耗的37%[19],其余的能量消耗為體系結構成本,并不是計算必須的.因此,在設計專用指令時,增加指令的粒度,將指令取指、譯碼和控制的開銷平攤到多個元素的計算上,可以有效提升執行效率.此外,當處理涉及大量數據的計算時,與傳統的標量指令相比,矩陣指令可以顯式地指定數據塊之間的獨立性,減少數據依賴檢測邏輯的大小.并且,矩陣指令還具有較高的代碼密度,因此我們這里主要關注數據級并行.
便簽存儲器(scratchpad memory).向量寄存器組通常出現在向量體系結構中,其中,每個向量寄存器都包含了一個長度固定的向量,并且允許處理器一次操作向量中的所有元素.便簽存儲器是在片上用于存儲臨時計算數據的高速內部存儲器,其具有直接尋址訪問、代價低以及可變長度數據訪問的特性.由于實現便簽存儲器的代價較低,因此通常部署較大尺寸的便簽存儲器并集成直接內存訪問(DMA)控制器,以便進行快速的數據傳輸.此外,考慮到密集、連續、可變長度的數據訪問經常發生在CNN 中,我們這里選擇使用便簽存儲器來替代傳統的向量寄存器組.
本節中,我們首先展示了專用指令集的構成,然后詳細介紹了在第1 節中提出的設計偏好下專用指令的功能和格式.在此基礎上,我們介紹了從基于深度學習框架的CNN 模型描述文件到專用指令的映射過程,并列舉了由專用指令實現的卷積層和池化層的代碼.
RV-CNN 指令集的構成見表1,其包含了數據傳輸指令、邏輯指令和計算指令.配合部分基礎的RV-32I 指令集(這里不再描述),該指令集可以完成典型的CNN 類計算.RV-CNN 指令集架構仍然和RISC-V 架構保持一致,屬于load-store 架構,僅通過專用的指令進行數據傳輸.并且,該指令集仍使用RV-32 中的32 個32 位通用寄存器,用于存儲標量值以及便簽存儲器的寄存器間接尋址.另外,我們設置了一個向量長度寄存器(vector-length register,簡稱VLR)來指定運行時實際處理的向量長度.下面對指令進行詳細介紹.

Table 1 An overview of RV-CNN表1 RV-CNN 指令集綜述
2.1.1 數據傳輸指令
為了靈活地支持矩陣運算,數據傳輸指令可以完成片外主存儲器和片上便簽存儲器之間可變大小的數據塊傳輸.圖1 展示了矩陣加載指令(MLOAD)的格式.

Fig.1 Matrix load (MLOAD)instruction format圖1 矩陣加載指令格式
圖1 中,Reg0 指定片上目標地址.Reg1、Reg2 和Reg3 分別指定矩陣的源地址、矩陣的大小和相鄰元素的跨度.具體而言,該指令完成數據從主存向便簽存儲器的傳輸,其中,指令的步幅字段可以指定相鄰元素的跨度,從而避免了內存中“昂貴的”矩陣轉置操作.相對應地,矩陣存儲指令(MSTORE)完成便簽存儲器向主存儲器方向的數據傳輸,其指令格式與MLOAD 相似,不過經常會忽略步幅字段以避免不連續的片外訪存.
2.1.2 矩陣計算指令
CNN 主要由卷積層、激勵層、池化層和全連接層組成,其中大部分計算都集中在卷積層[20].在卷積層的計算中,卷積核在輸入特征圖上連續移動,并在重合區域執行點積以生成下一層的輸入數據.在此過程中,同一卷積核在特征圖的不同區域之間的計算是獨立的,不同卷積核在特征圖的相同區域的計算也是獨立的.為了充分利用卷積計算中的并行性,我們采用Im2col(image to column)算法將2-D 卷積運算轉換為矩陣乘法運算(算法示意如圖2 所示).

Fig.2 Matrix multiplication version of convolution圖2 卷積運算的矩陣乘法版本
將2-D 卷積映射到矩陣乘法操作后,可以很自然地使用MMM(matrix-multiply-matrix)指令執行該操作.其指令格式如圖3 所示,其中,Reg0 指定矩陣輸出的便簽存儲器中的目的地址;16~12 位是指令的功能字段,指示矩陣乘運算.Reg1 和Reg2 分別指定矩陣1 和矩陣2 的在便簽存儲器中的源地址.Reg3 中的4 個字節分別代表矩陣的高(H)、寬(W)、卷積核大小(K)、卷積步長(S).考慮到實際執行中分片技術的使用,這里使用單個字節存儲相應的信息是足夠的.因此,卷積操作執行時的參數信息被打包成32’b{H,W,K,S},并由Reg3 指定.同時,由于數據分片載入,其產生的中間結果往往需要累加.這里不設置特定的矩陣加法指令而是設計了MMS 指令.該指令在完成矩陣乘法計算后,將部分結果寫入目標地址時與該地址原有的值累加后再存儲,使得在完成累加的同時減少數據的重新載入.該指令的格式和各字段含義均與MMM 指令一致,由功能字段指定該指令,故不再展示.此外,為了更大程度地利用數據局部性并減少對同一地址的并發讀/寫請求,我們選擇采用專用的MMM 指令執行矩陣乘法,而不是將其分解為更細粒度的指令(例如,矩陣向量乘和矢量點積).

Fig.3 Matrix multiply matirx (MMM)instruction format圖3 矩陣乘矩陣指令格式
全連接層通常在整個卷積神經網絡的尾部以對之前各層學得的特征進行映射達到分類效果.全連接層的計算可以用矩陣向量乘法表示,而MMM 指令在不同的參數下同樣可以表示全連接層的計算,因此卷積層和全連接層可以復用相同的計算單元.
2.1.3 矩陣邏輯指令
融合(fusion)[21]作為目前DNN 加速器設計中常用的技術,通過將部分層加以融合,從而以一次數據的加載、存儲替代單獨層的數據輸入輸出操作來最小化帶寬限制.融合操作的優勢以及目前CNN 中激活層通常緊接在卷積層或全連接層之后的特點,使得設計相應的粗粒度指令將兩者融合執行是非常適合的.而且激勵層不改變輸入張量的尺寸且激活函數逐元素進行激活操作,其需要的參數較少.因此,我們設計了MMMA 指令,使矩陣相乘得到卷積層或全連接層的部分最終結果后可經過激活操作后輸出,其指令格式與各字段含義均和MMM 指令一致,由功能字段指定該指令.不過,我們仍然保留了激活指令,以完成對輸入的數據進行激活操作,其指令格式如圖4 所示,其指令中的31~27 位用來決定激活函數的選擇,如ReLU()/sigmoid()/Tanh().

Fig.4 Matrix activation (MACT)instruction format圖4 矩陣激活指令格式
池化層通過降采樣將輸入數據的每個窗口子采樣到單個池輸出以減小輸入圖片的尺寸.實際上,卷積神經網絡中相較于卷積層和全連接層,其余層包含了很少的計算且被數據訪問時間限制.在某些CNN 模型中,對池化層和相鄰層采用融合技術同樣是有效的.但是,不同于激活層在CNN 中的位置相對固定且按元素操作,池化層仍具有一定的靈活度,如3 個卷積層堆疊后池化.于是,這里我們仍將池化層當作單獨的層來處理.用于進行最大值池化的MXPOOL 的指令格式如圖5 所示.其中,Reg0、Reg1、Reg2 分別表示輸出數據的目標地址、輸入數據的源地址和輸入數據的長度.借鑒設計MMM 指令的思想,觀察到池化窗口通常為2×2、3×3、5×5 等小尺寸而且通常采用分片技術處理輸入數據,所以使用單個字節分別表示一次分片可處理的輸入矩陣的高(H)、寬(W)、池化窗口大小(K)和步長(S)是足夠的.這些必要信息進而被打包為32 位值,由Reg3 指定.

Fig.5 Matrix maximum (MXPOOL)instruction format圖5 矩陣池化指令格式
RV-CNN 指令生成流程如圖6 所示.其中,CNN 模型描述文件可以是深度學習工程師熟悉的Caffe、TensorFlow 或Pytorch 等流行框架下的描述文件.由模型分析器對該描述文件進行解析以生成用于模型構建的參數信息和重排后的權重信息.在此基礎上,應根據網絡參數信息構建數據流圖并提取算子,然后在不同的融合策略下將提取出的算子映射至指令池(RV-CNN 指令集)中的不同指令.由于我們設計的指令均為粗粒度指令,這里應提取粒度適合的算子才能映射至目標指令集.在專用指令提取后,應根據硬件的參數信息,如片上便簽存儲器的大小和硬件計算資源規模來決定分片大小.同時根據復用策略,如輸入復用或權值復用等對指令進行編排以生成最終的代碼.其中,應使用RV32 基礎指令集將參數信息加載至寄存器并完成循環控制.

Fig.6 RV-CNN instructions generation process圖6 RV-CNN 指令生成流程
為了闡述提出的專用指令集的用法,我們列舉了使用RV-CNN 構建的CNN 中兩個具有代表性的部分,即卷積層和池化層.其中,卷積層的實現通過融合指令包含了激勵層的操作.而全連接層的代碼實現與卷積層代碼類似,僅在配置參數上略有不同,故不作列舉.
2.3.1 卷積層代碼示例
RV-CNN 實現的卷積層代碼如圖7 所示,其中,左側是在Caffe 框架中編寫的卷積層代碼(用以示意),其完成對輸入特征圖(14×14×512),使用512 組尺寸為3×3、步幅為1 的卷積核進行特征提取的過程.圖中右側則是使用專用指令完成相同功能的示意代碼,其中假設硬件片上資源充足且數據排列順序合適.
由于指令從寄存器中獲取參數信息,因此我們首先需要向寄存器中加載必要的信息.這里首先加載立即數0×0E0E0301 至$5 寄存器,根據第2 節對指令格式的描述,該32 位數據中由高至低的4 個字節分別代表了輸入數據的高度(14)、寬度(14)、卷積核尺寸(3)以及步幅(1).之后設置向量寄存器VLR 為16,代表一次處理的向量長度為16.由于采用分片技術,這里設置循環計數器$11、$12 來完成深度方向和不同卷積核的遍歷.隨后,通過在寄存器$6、$8、$10 中加載數據在片外DDR 中的實際地址,以便通過MLOAD/MSTORE 完成數據傳輸.以上寄存器中的信息應由指令生成器或者用戶根據網絡模型以及硬件參數信息生成.在此基礎上,開始實際計算過程.首先分別將數據從片外0×30000 和0×50000 處加載至由$1 和$2 指定的片上目的地址.數據加載完畢后,通過執行MMM 指令完成計算.計算過程中的中間結果保存在片上便簽存儲器中.之后的計算通過使用MMMS 指令完成計算與片上中間結果累加,以減少不必要的片外訪存.最終,通過執行MMMSA 指令完成部分最終結果的激活,并由MSTORE 指令將結果傳輸至片外.

Fig.7 Convolutional layer code example implemented by RV-CNN圖7 RV-CNN 實現的卷積層代碼示例
2.3.2 池化層代碼示例
RV-CNN 實現的池化層代碼如圖8 所示,左側仍以Caffe 框架中編寫池化層代碼作功能示意,其表示對輸入特征圖(14×14×512),使用2×2、步幅為2 的池化窗口進行最大值采樣.圖右側則是使用專用指令完成相同功能的示意代碼,其中仍假設硬件片上資源充足且數據排列順序合適.
由于池化層不包含權重數據且不在深度方向上累積,在輸入圖片大小合適的情況下,其RV-CNN 實現的代碼比卷積層代碼要簡潔.在向相應寄存器中加載完參數后,利用MLOAD 指令將待處理數據從片外0×10000($6)處加載至片上目的地址$1 處.輸入數據加載完畢后,使用MXPOOL 指令進行降采樣并將結果存儲在片上臨時地址$5 處,采樣結束后,則由MSTORE 將結果傳輸至片外地址0×40000($7)處,該過程中輸出并不會在片上累加.代碼中的循環計數器是為了在輸入數據深度方向上遍歷,一次載入、池化、載出完成一次分片數據的采樣,之后更新載入、載出地址以及計數器值.

Fig.8 Pooling layer code example implemented by RV-CNN圖8 RV-CNN 實現的池化層代碼示例
目前,在面向神經網絡領域的專用指令集中,Cambricon 指令集被認為是最具代表性的指令集之一,而基于RISC-V 架構的向量指令集擴展(RV-V)也被認為是加速神經網絡計算的指令集.因此,本節將圍繞指令集的適用范圍、粗細粒度以及映射機制等方面,將RV-CNN 與以上兩種典型指令集進行定性分析和對比.
適用范圍.RV-V 指令集的建立旨在利用應用中的數據級并行,其可廣泛應用于科學計算、數據信號處理以及機器學習等領域.Cambricon 指令集則是面向神經網絡領域,如CNN、循環神經網絡(RNN)以及長短期記憶網絡(LSTM)等10 余種網絡模型而設計的指令集.相比之下,RV-CNN 指令集著重針對神經網絡領域中的CNN 而設計,其中涉及的運算類型較少.因此,前兩者針對的領域更廣泛,設計的難度也更大,這在指令集包含的指令類型和數目上也有所體現.RV-V 指令集已經包含了超過60 條指令(草稿版本0.8),Cambricon 指令集中包含了47條指令,而RV-CNN 指令集僅包含了10 條指令.
粗細粒度.RV-V 和RV-CNN 指令集中分別包含了向量和矩陣指令,而Cambricon 指令集中則包含了標量、向量以及矩陣3 類不同的指令.Cambricon 之所以包含標量指令是因為其在概念上是一個完備的神經網絡指令集,但其中用于加速計算的仍是向量和矩陣指令.因此,在指令粒度層面上,RV-CNN 指令集是三者中指令粒度最大的,Cambricon 指令集其次,由于RV-V 指令集中均是向量指令,相比之下粒度最小.這也與指令集的適用范圍相關,由于在設計RV-V 指令集時針對的應用領域最為廣泛,因此需要從多種計算操作中提取共性部分.考慮到硬件規模及能耗限制,這一過程往往需要結合算法特性,將不同的計算過程不斷地向下拆分以尋求計算共性,提高指令集的表達能力,因此相較于前兩者RV-V 指令集的指令粒度最小.
代碼映射機制.Cambricon 指令集的代碼映射是基于框架的,其為流行的編程框架提供適配的機器學習高性能庫與軟件運行時支持,向上為框架提供豐富的算子和計算圖方法以構造整個網絡,向下通過調用內置驅動產生指令以控制硬件.RV-CNN 指令集的代碼映射過程以基于框架的模型描述文件開始,不同于Cambricon 對框架進行修改,RV-CNN 僅對框架下的模型描述文件進行分析,從而提取模型結構及權重信息,進而配合融合策略建立模型中算子和指令間的映射關系,之后根據復用策略進行指令編排,最終經匯編形成可執行文件.RV-V 指令集目前處于正在進行的狀態,還未提供可使用的編譯器來完成對代碼的自動矢量化過程,仍需要用戶手寫匯編指令.但其中涉及到大量細粒度的向量指令,這給編程過程中寄存器分配以及指令編排增加了難度.
本節首先介紹了包含RV-CNN 指令擴展的開源處理器核的整體結構,并詳細介紹了指令的執行流程.隨后講述了與RV-CNN 指令相對應的矩陣單元的組成及其子單元的功能,其中詳細展示了矩陣乘法單元的結構,最后介紹了有關矩陣單元的優化細節.
包含了RV-CNN 擴展的RISC-V 處理器核的主要功能部件以及簡化的流水線結構如圖9 所示.可見,其包含了基本的5 個流水線階段:取指、譯碼、執行、訪存和寫回.其中,矩陣計算單元處于流水線的執行階段,用于完成矩陣指令的執行.在取指、譯碼階段之后,基礎指令集中的指令將進入ALU,然后進入下一個階段.當譯碼階段解析出當前指令是矩陣指令后,譯碼器從寄存器中獲得相應信息并保存,待下一個周期送入矩陣單元.矩陣單元根據接受的指令信息并檢測相應功能部件的狀態以確定是否執行.由于片上便簽寄存器的地址空間用戶可見,矩陣單元可以通過矩陣數據傳輸指令和內存進行交互,因此,矩陣指令進入矩陣單元后不會經過訪存和寫回兩個階段,而其余指令不通過矩陣單元,其訪存仍通過高速緩存(cache).這樣可以避免不必要的數據依賴性檢測和硬件自動的數據換入換出.此外,由于矩陣單元包含了大量的計算單元,其內部有自己的流水線結構,譯碼器根據矩陣單元能否接受矩陣指令信息來決定是否停止流水線.鑒于矩陣指令連續、大量的數據訪問,我們在便簽存儲器外集成了DMA 控制器,以便滿足矩陣單元的數據訪問需求.需要注意的是,矩陣單元完成計算和邏輯類指令所涉及的數據需要已經存在于片上,這需要程序的嚴格控制.

Fig.9 A simplified block diagram of processor core with RV-CNN extension圖9 包含RV-CNN 擴展的處理器核簡化框圖
矩陣單元的整體結構如圖10 所示,其內部主要包含了輸入輸出單元、矩陣乘法單元、激活單元、池化單元以及內部控制器,其中,橙色和灰色箭頭分別表示控制流和數據流.矩陣單元接收傳入的指令信息以及寄存器信息后存儲到隊列中.內部控制器(作為有限狀態機)是矩陣單元的控制中心,其根據控制信息將喚醒子組件(如果可用)以完成相應任務.否則,它將生成一個反饋信號以指示相應的功能單元正忙.緩沖模塊本質上是一個片上存儲器,矩陣單元中的計算核心從中獲取數據并將產生的結果寫入.除融合指令會同時啟動多個計算核心外,計算單元大致上與粗粒度指令一一對應.最后,輸入輸出模塊則負責根據有效地址在矩陣單元與片上便簽存儲器之間進行數據傳輸.
由于矩陣乘法單元被卷積層和全連接層共用,其承擔了大部分計算,因此該單元的實現對性能至關重要.這里我們采用了脈動陣列結構實現的矩陣乘法,其結構如圖10 右側部分所示.脈動陣列是一種高效且簡單的矩陣乘法實現方式,其通過二維網格將MAC(multiply-accumulate)單元綁定在一起,除陣列的最外側層(這里是最左側和最上側)的計算單元直接與片上緩沖相連以獲取數據外,其余計算單元均從其鄰居中獲得輸入.這種方式在MAC 陣列規模變大時將顯著減少片上緩沖的扇入扇出.同時,數據在MAC 單元之間流動性地傳遞也增加了數據復用.例如,當MAC 陣列為12×16 時,矩陣B中的元素按行在不同時刻由左至右在陣列中傳遞,數據輸出時復用了16 次;類似地,矩陣A中的元素按列在不同時刻由上至下在陣列中傳遞,輸出時復用了12 次.在這一過程中,配合流水線優化,每周期只需要向陣列輸入28 個數,就可以進行192 個MAC 操作.此外,短的局部互連也降低了布局布線的難度,因此,這里我們選擇使用脈動陣列作為矩陣乘法的實現方式.

Fig.10 The block diagram of the matrix unit圖10 矩陣單元的結構示意圖
數據復用.在處理卷積層時,對輸入數據進行Im2col 操作將在內存占用和帶寬方面帶來不菲的開銷.例如,當卷積核步幅為1 時,與原始輸入數據相比,轉換后的輸入矩陣消耗的內存約為原始的K×K倍.為了保留Im2col操作帶來的好處,同時減少額外的開銷,我們實現了片上Im2col 緩沖區,并根據地址在片上對切片數據進行數據重排和展開.設置Im2col 緩沖區可以有效地增加數據復用,雖然并未減少輸入數據的訪問次數,但使用開銷較小的片上訪問代替了開銷大的片外訪問,從而大大減少了該操作造成的額外的數據訪問開銷和外部帶寬壓力.
數據量化.傳統上,無論是CNN 的訓練階段還是預測階段,其數據類型均采用32 位單精度浮點數,這主要是因為它是現代GPU 的標準數據格式.但研究發現,CNN 對有限的數值精度具有固有的魯棒性,在預測階段使用浮點計算并不是必須的.通過重訓練和特定的微調手段,采用定點數進行預測造成的精度損失可以忽略不計(小于1%)[22].對于許多CNN 來說,甚至8 位位寬就可以達到足夠的精度.之所以采取量化操作,是因為權重和激活的低位寬表示形式有助于避免昂貴的浮點計算,同時顯著減少帶寬需求和內存占用.DianNao[11]中顯示,在臺積電65nm 工藝條件下,實現32 位乘法器的面積和功耗要比16 位乘法器的功耗高一個數量級.在這種權衡之下,本文中矩陣單元的所有計算核心均采用16 位定點數.
為了驗證所提出的專用指令的有效性,我們在FPGA 平臺上構建了包含該指令集擴展的基于RISC-V 架構的處理器核.在此基礎上,使用AlexNet、VGG16 兩種不同規模的卷積神經網絡進行評測,并將該原型系統與Cambricon、CPU、GPU 和其他FPGA 加速器進行對比分析.
(1)原型系統的FPGA 實現
我們使用ZC702 開發板作為實驗平臺,該平臺為嵌入式FPGA 平臺,其中,包含了一塊XC7Z020 FPGA 芯片和1GB DDR3 板載內存,可提供4.2GB/s 的片外數據存取帶寬.RISC-V 基礎內核及矩陣單元的控制使用硬件描述語言Verilog 來完成,矩陣單元中的子計算單元設計則通過Xilinx Vivado HLS 2017.4 高層次綜合工具完成,完整的硬件工程通過Xilinx Vivado 2017.4 集成開發環境進行綜合和實現.
(2)CPU 測試基準
我們使用Caffe 深度學習框架(CPU-only)在CPU 平臺上部署了兩種目標網絡模型.CPU 配置為Intel i7-4790K,其中包含了4 物理核心,最大線程數為8,工作頻率為4GHz,并配有16GB DDR3 內存.
(3)GPU 測試基準
GPU 版本的測試仍然通過Caffe 深度學習框架(GPU-only)并通過CuDNN5.1 加速庫在GPU 平臺上部署兩種目標網絡模型.GPU 配置為NVIDIA Tesla K40C,其最大可支持2 880 個硬件線程,工作頻率為745~875MHz,并配有12GB GDDR5 顯存.
在本節中,我們首先報告了原型系統在FPGA 平臺上的資源消耗和功耗,然后圍繞代碼密度、性能及能效3個方面將該設計與Cambricon、CPU、GPU 以及以往基于FPGA 的加速器進行對比分析.
通過查看原型系統在Vivado 工具中的部署報告,我們獲得了其在目標平臺的各項資源消耗以及FPGA 的功耗,見表2.
(1)與Cambricon、CPU、GPU 平臺的代碼密度、性能及能效對比
代碼密度.本文提出的專用指令不僅適用于加速CNN 應用,而且還為具有類似計算模式的其他深度學習算法(如MLPs)提供支持.通過使用RV-CNN、C 和CUDA-C 實現流行的CNN 模型并測量其代碼長度,我們對比了RV-CNN 指令與基礎RV32、ARM、x86 和GPU 的代碼密度,結果如圖11 所示,其中,以RV-CNN 指令集實現的代碼長度為基準.可見,相比于原本的RV32(IMF)指令集,擴展RV-CNN 后代碼長度減少了10.10 倍.相比于GPU、x86 與ARM 指令集,RV-CNN 的代碼長度分別減少了1.95 倍、8.91 倍和10.97 倍.以x86 指令的代碼長度為基準,RV-CNN 的代碼長度相比于Cambricon 減少了1.51 倍.
性能及能效.圖12 展示了在兩種神經網絡(AlexNet 和VGG16)的推理過程測試下,該設計與CPU 和GPU的性能、能效對比,其中,所有數值均可歸一化到CPU 的實驗結果上.可見,在Xilinx ZC702 平臺上,該設計在執行兩種網絡的性能上均優于CPU,分別達到2.64 倍和4.23 倍的加速效果.但是由于該平臺是嵌入式平臺,用于計算的硬件資源DSP(使用91%)成為主要的性能瓶頸,因此在執行兩種網絡的性能上均落后于GPU.在能效方面,以每瓦特性能(GOPS/w)為基準,該設計在AlexNet 和VGG-16 的推理上,相較于CPU 分別提升了101.49 倍和167.62 倍;相較于GPU 分別提升了1.06 倍和1.40 倍.由于Cambricon 加速器為ASIC 設計,因此我們這里對比了性能密度(op/multiplier/cycle),即每周期乘法器完成的操作數.以GPU 的測試數據為基準,RV-CNN 相比于Cambricon 有1.16 倍的提升.
(2)與其他FPGA 加速器的對比
表3 列出了本設計與已有的典型FPGA 加速器的對比結果.由于不同的工作采用了不同的量化策略和不同的硬件進行部署,因此很難選擇出一種有效且精確的比較方法.若以每秒千兆操作數(GOPS)作為性能評估標準,以前的工作可以實現比我們更好的性能.但是,更高的性能背后是更多的資源消耗,例如DSP 和LUT 資源,因而功耗也會相應增加.若以每瓦特的性能(GOPS/w)作為能效評估標準,與以往的加速器相比,我們的設計在保持靈活性下仍具有較高的能效.

Fig.11 The reduction of code length against Cambricon,GPU,x86,RV32,and ARM圖11 RV-CNN 相對于Cambricon、GPU、x86、RV32 以及ARM 的代碼長度減少

Fig.12 Performance and energy efficiency comparison between prototype system and CPU and GPU圖12 原型系統與CPU、GPU 的性能、能效對比

Table 3 Comparison of the prototype system and previous FPGA-based accelerator deployment表3 原型系統與以往基于FPGA 的加速器部署對比
CNN 在圖像識別、目標檢測領域的廣泛應用使其性能至關重要.本文通過分析典型CNN 的計算模式,提出了一種高效且易于實現的專用指令集RV-CNN,其包含了10 條粗粒度的矩陣指令,可以靈活地為典型CNN 模型推理過程提供支持.在此基礎上,我們介紹了CNN 模型描述文件到RV-CNN 指令的映射過程.隨后通過定性分析,從不同方面將RV-CNN 與典型專用指令集進行比較.在指令實現方面,我們將該指令集擴展進了基于開源架構RISC-V 的處理器核,并以相對緊耦合的方式將對應的矩陣單元嵌入經典的5 級流水線中.最后,本設計在Xilinx ZC702 平臺對上進行綜合實現,并以典型的神經網絡進行測試.結果顯示,相比于Intel i7-4790K 處理器和Tesla k40c GPU,該原型系統具有最高的能效和代碼密度.此外,與先前的加速器相比,該原型系統在保持靈活性的同時也展現了不錯的能效.
目前新型CNN 網絡層出不窮,還需考慮對其中諸如深度可分離卷積等操作進行指令優化以提高執行效率.此外,擴展指令的設計與實現應針對RISC-V 特點做出協同優化.最后,根據模型及硬件信息執行的代碼映射過程還未自動化,未來,計劃在以上方面加以改進.