廖漢松,吳朝暉,李 斌
(1.華南理工大學(xué)微電子學(xué)院,廣州510641;2.人工智能與數(shù)字經(jīng)濟(jì)廣東省實(shí)驗(yàn)室(廣州),廣州510330)
RISC-V 是一種基于精簡指令集計(jì)算(Reduced Instruction Set Computing,RISC)原則的開源指令集架構(gòu),由于其相較于x86、ARM 架構(gòu)可以更低成本地針對不同應(yīng)用領(lǐng)域進(jìn)行定制和優(yōu)化,因此成為近年來的研究熱點(diǎn)[1-3]。另一方面,人工智能現(xiàn)已滲透到各行各業(yè),出現(xiàn)了諸多智慧化產(chǎn)品。在主流的運(yùn)算平臺中,GPU 功耗和成本過高[4],F(xiàn)PGA 資源和速度有限,ASIC 通用性較差[5-7],技術(shù)積累深厚的CPU 平臺更適合對成本敏感、算法靈活多變和計(jì)算步驟復(fù)雜的領(lǐng)域,但目前通用的CPU 仍難以滿足神經(jīng)網(wǎng)絡(luò)大規(guī)模計(jì)算的要求。
由于登納德縮放比例定律失效和摩爾定律減緩,物聯(lián)網(wǎng)領(lǐng)域常用的CPU 平臺難以單純地通過提高處理器工作頻率、集成更多核心等手段來滿足神經(jīng)網(wǎng)絡(luò)算法對端側(cè)算力日益增長的需求[8]。采用領(lǐng)域?qū)S眉軜?gòu)(Domain Specific Architecture,DSA),面向領(lǐng)域應(yīng)用定制處理器核心和集成異構(gòu)核心能夠更有效地提高能效,然而此方案卻受限于主流x86、ARM 架構(gòu)的商業(yè)局限性而難以普及,而具有先進(jìn)設(shè)計(jì)理念優(yōu)勢的開源架構(gòu)RISC-V 則能有效避免這些問題。
為應(yīng)對計(jì)算強(qiáng)度特別高的算法(如神經(jīng)網(wǎng)絡(luò)算法),本文參考領(lǐng)域?qū)S锰幚砥骷軜?gòu),基于RISC-V 指令集,針對特定應(yīng)用領(lǐng)域的需求設(shè)計(jì)專用拓展指集處理器,利用卷積神經(jīng)網(wǎng)絡(luò)(Convolutional Neural Network,CNN)的并行性對常見網(wǎng)絡(luò)運(yùn)算進(jìn)行硬件加速,使其同時具備CPU 的通用性、靈活性和ASIC 的高能效優(yōu)勢。
RISC-V 是2010年由伯克利加州大學(xué)研究者研發(fā)的開源指令集架構(gòu),相比于x86 和ARM 等架構(gòu),其無需考慮前向兼容性,可對多年來舊架構(gòu)暴露的問題和缺陷進(jìn)行完善改進(jìn),而無須將一些冗余低效甚至錯誤的設(shè)計(jì)保留在其中[2],如去除分支延遲槽、去除使用頻率低卻影響處理器亂序執(zhí)行的條件執(zhí)行指令、僅實(shí)現(xiàn)一種簡潔的內(nèi)存尋址模式等。編譯器軟件隨著多年發(fā)展得以完善,許多使用硬件優(yōu)化的手段可被軟件取代,硬件設(shè)計(jì)可以更加簡潔。以往依賴于硬件加速的設(shè)計(jì),可能已經(jīng)不再發(fā)揮作用,甚至阻礙優(yōu)化。RISC-V 還采用了不同尋常的模塊化設(shè)計(jì),將不同的指令劃分成可選的拓展。使用基礎(chǔ)指令集+拓展指令集的模式,除了基礎(chǔ)指令集必須實(shí)現(xiàn)外,還可以根據(jù)應(yīng)用的需求、高性能或是低功耗,選擇是否添加這些拓展指令集。而且這個開放的指令集中保留了大量的操作碼空間,以便添加用于領(lǐng)域?qū)S眉铀倨鞯淖远x指令。RISC-V 的這種設(shè)計(jì)既能滿足軟件生態(tài)的兼容,又能在保證處理器盡可能精簡的同時添加領(lǐng)域?qū)S眉铀倨鳌?/p>
本文定制的Rocket 處理器是由伯克利大學(xué)的ASANOVI? 等人開發(fā)的一款經(jīng)典5 級流水線的單發(fā)射標(biāo)量處理器核心[9]。該處理器由基于Chisel(Constructing Hardware in a Scala Embedded Language)構(gòu)建的開源SoC 設(shè)計(jì)平臺Rocket Chip 生成。面向?qū)ο笳Z言使得開發(fā)硬件更加靈活,通過Rocket Chip平臺,可以對處理器進(jìn)行高度定制化。除了面向特定應(yīng)用開發(fā)專屬的自定義模塊,只需要調(diào)整參數(shù)即可對已有的處理器核心數(shù)、指令集拓展、Cache 配置、總線等進(jìn)行調(diào)整,最后編譯出所需的定制處理器。由于專用指令集處理器的設(shè)計(jì)十分復(fù)雜,生產(chǎn)成本也很高,為確??煽啃裕话愣紩捎媚M器對處理器進(jìn)行建模和驗(yàn)證。由于Rocket Chip 平臺原本就由高級語言進(jìn)行構(gòu)建,因此能夠快速生成配套的C++模擬器,大幅縮短處理器的驗(yàn)證時間,降低開發(fā)成本。
此外,Rocket Chip 平臺還提供RoCC(Rocket Custom Coprocessor)接口用于加入自定義的加速器。加速器可使用以下3 種方式接入:
1)接入處理器的指令處理流水線。Rocket 核將相關(guān)指令發(fā)射到RoCC 接口,加速器只能通過指令和通用寄存器獲取命令與數(shù)據(jù),完成特定運(yùn)算后給出響應(yīng)并回傳數(shù)據(jù)到通用寄存器。
2)增加一級數(shù)據(jù)高速緩存(L1 D-Cache)訪問接口。L1 D-Cache 中緩存了處理器頻繁訪問的數(shù)據(jù),加速器直接通過高速緩存讀寫數(shù)據(jù),能夠更高效地獲取所需處理數(shù)據(jù)和回寫結(jié)果。
3)完全解耦。通過總線直連到外部內(nèi)存系統(tǒng),更適用于數(shù)據(jù)龐大且重用性低的情況。
為獲得更好的性能,神經(jīng)網(wǎng)絡(luò)研究向更深、更復(fù)雜的方向發(fā)展。然而在使用神經(jīng)網(wǎng)絡(luò)落地解決實(shí)際問題時,受限于終端設(shè)備的算力、內(nèi)存大小和低功耗、低成本的應(yīng)用場景,很多經(jīng)典的網(wǎng)絡(luò)模型都難以實(shí)現(xiàn)。因此,研究者著手于網(wǎng)絡(luò)優(yōu)化,通過以1×1 和3×3 卷積核取代大尺寸的卷積核、以全局池化層取代全連接層等手段簡化模型的復(fù)雜度,減少網(wǎng)絡(luò)參數(shù)的數(shù)量[10-12]。經(jīng)典網(wǎng)絡(luò)模型與輕量化網(wǎng)絡(luò)模型比較[13-15]如表1所示??梢钥闯觯瑴?zhǔn)確率相近的SqueezeNet網(wǎng)絡(luò)與AlexNet網(wǎng)絡(luò)參數(shù)量相差約50 倍,前者顯著降低了計(jì)算時對算力的需求和內(nèi)存的消耗。
表1 經(jīng)典網(wǎng)絡(luò)模型與輕量化網(wǎng)絡(luò)模型的對比Table 1 Comparison of classical network model and lightweight network model
本文提出如圖1所示的專用指令集處理器設(shè)計(jì)方案,主要分為兩個部分,即Rocket 核和用于卷積神經(jīng)網(wǎng)絡(luò)運(yùn)算的加速器。為使處理器盡可能精簡,在Rocket 核部分選擇RV32IMAFC 架構(gòu),其中32 位寬的處理器足以覆蓋物聯(lián)網(wǎng)設(shè)備的內(nèi)存范圍。Rocket 核負(fù)責(zé)完成算法的邏輯控制和圖像預(yù)處理,在此基礎(chǔ)上使用自定義拓展指令觸發(fā)加速器完成CNN 中的密集計(jì)算。通過自定義拓展指令配置卷積神經(jīng)網(wǎng)絡(luò)各層的信息,對輸入數(shù)據(jù)進(jìn)行分組并靈活調(diào)整加速器的數(shù)據(jù)通路,從而適應(yīng)不同大小的輸入數(shù)據(jù),減少片上緩存需求,同時適應(yīng)輕量化網(wǎng)絡(luò)的常用運(yùn)算操作和結(jié)構(gòu)。加速器接收到相關(guān)指令后,從片外存儲器中獲取相應(yīng)數(shù)據(jù),根據(jù)指令完成CNN 中卷積、激活、局部池化和全局池化等耗時操作,并將結(jié)果回寫存儲器以待后續(xù)處理。加速器沒有接入D-Cache,而是以更大位寬的獨(dú)立讀寫端口對片外存儲器進(jìn)行訪問,完成與Rocket核的數(shù)據(jù)傳遞。由于卷積神經(jīng)網(wǎng)絡(luò)數(shù)據(jù)量龐大,因此若不能匹配Cache 大小,則會導(dǎo)致訪存命中率低和數(shù)據(jù)頻繁進(jìn)出,從而降低效率。
圖1 本文處理器系統(tǒng)框圖Fig.1 System block diagram of the proposed processor
本設(shè)計(jì)中處理器并未使用高性能和過多配置,目的是節(jié)省更多空間留給CNN 加速器運(yùn)算單元,具體配置如表2所示。
表2 處理器配置Table 2 Configuration of processor
本文設(shè)計(jì)了如圖2所示的2種指令用于CNN加速,包括用于配置加速器寄存器的設(shè)置類指令和用于計(jì)算的操作類指令。指令中第0 位~第6 位為opcode 字段,處理器解碼得到0001011 后會將此類指令發(fā)射到加速器模塊,第28 位~第31 位的funct4 字段用于標(biāo)識不同的指令類型,最高位取0 表示為設(shè)置類指令,取1 表示為操作類指令。位操作類指令的第28 位~第30 位分別用于指定加速器是否進(jìn)行卷積、池化操作,第15 位~第19位的rs1字段、第20位~第24位的rs2字段、第25位~第27 位的offset3 字段則用于指定主處理器通用寄存器堆中的編號。其中,offset3 為相對rs2 指定寄存器編號的偏移量,即第3 個寄存器通過[rs2+offset3]來尋址,因此,每條指令最多可傳遞3 個32 位的源操作數(shù)對加速器進(jìn)行配置。第12 位的xs2 字段、第13 位的xs1 字段、第14 位的xd 字段用于標(biāo)識是否使用相應(yīng)字段指定的通用寄存器進(jìn)行數(shù)據(jù)傳遞。xs1 設(shè)置為1 表示使用rs1、rs2 指定的通用寄存器傳遞數(shù)據(jù)。操作指令中xs2設(shè)置為0,表示不需要配置第3 個通用寄存器數(shù)據(jù)。由于設(shè)計(jì)中加速器的運(yùn)算數(shù)據(jù)通過獨(dú)立訪存端口進(jìn)行傳遞,并不需要回傳到主處理器的通用寄存器堆,因此xd設(shè)置為0,且修改原本用于指定目的寄存器的第7 位~第11 位字段用于傳遞更多信息。設(shè)置類指令中修改為addr 字段,用于指定3 組加速器中用于配置的寄存器,分別存儲輸入數(shù)據(jù)、輸出數(shù)據(jù)和網(wǎng)絡(luò)參數(shù)信息。操作類指令中修改為info 字段,用于指定各計(jì)算操作的類型,如卷積和池化操作的窗口大小、運(yùn)算步長、數(shù)據(jù)四周是否補(bǔ)零。加速器并未實(shí)現(xiàn)太細(xì)顆粒度加速,而是以每層為單位進(jìn)行加速。雖然會犧牲一定靈活性,但是細(xì)顆粒不利于進(jìn)一步優(yōu)化運(yùn)算,且數(shù)據(jù)頻繁進(jìn)出加速器影響效率。
圖2 卷積神經(jīng)網(wǎng)絡(luò)專用拓展指令Fig.2 Special extension instructions of convolutional neural network
2.2.1 數(shù)據(jù)量化
為在有限資源下實(shí)現(xiàn)CNN 加速器設(shè)計(jì),本文采用英偉達(dá)的使用飽和截取的線性量化方案[16],將網(wǎng)絡(luò)權(quán)重和激活值量化為8 bit。經(jīng)SqueezeNet 網(wǎng)絡(luò)驗(yàn)證,與浮點(diǎn)卷積相比,量化后雖然Top1 準(zhǔn)確率下降了0.58%,Top5 準(zhǔn)確率下降了1.39%,但仍能保持較高準(zhǔn)確率。
2.2.2 卷積運(yùn)算單元設(shè)計(jì)
卷積模塊運(yùn)算單元如圖3所示,采用內(nèi)存帶寬占用相對較低的二維PE 陣列,由16×16 個PE 陣列組成,支持并優(yōu)化輕量化網(wǎng)絡(luò)中常用的1×1 和3×3 兩種大小的卷積,通過不同映射實(shí)現(xiàn)多種并行方式和數(shù)據(jù)復(fù)用。此外,為精簡常規(guī)PE 陣列之間繁瑣的互連,本模塊以廣播數(shù)據(jù)的方式,將權(quán)值、輸入特征圖分別從水平方向、垂直方向加載到PE,并且PE 計(jì)算結(jié)果僅會在一行內(nèi)累加。
圖3 卷積模塊Fig.3 Convolution module
卷積過程采用保留卷積核的方式,以1×1 卷積為例,即完成當(dāng)前16 輸入通道內(nèi)所有數(shù)據(jù)與卷積核的卷積、卷積核徹底用完,才加載下一組16 通道輸入特征圖和卷積核。遍歷所有輸入通道后才能獲得完整的輸出特征圖,中間產(chǎn)生的部分和數(shù)據(jù)需要保存在輸出緩存中。此種方式能夠更好地提高數(shù)據(jù)重用性,卷積時可復(fù)用輸入緩存內(nèi)和PE 內(nèi)的輸入特征圖,也便于之后模塊實(shí)現(xiàn)3×3 的池化操作。
為方便闡述該結(jié)構(gòu)實(shí)現(xiàn)卷積的運(yùn)算過程,對PE 陣列進(jìn)行簡化,并分別對1×1 和3×3 兩種卷積映射進(jìn)行分析。
1×1卷積映射如圖4(a)所示。每個PE 都可以獨(dú)立完成運(yùn)算,并行計(jì)算6 通道輸入、6 通道輸出。PE 陣列不需要分組,數(shù)據(jù)也不需要變換。6 通道輸入特征圖分別并行加載至6 列PE,計(jì)算結(jié)果輸出至每行加法樹,可同時輸出6 通道輸出特征圖。由于1×1 卷積不需要復(fù)用多行數(shù)據(jù),PE 內(nèi)緩存不需要進(jìn)行額外控制,計(jì)算完該6通道輸入后,向緩存請求下一組權(quán)值和6通道輸入,因此遍歷所有通道輸入特征圖并完成部分和疊加,即可得到6 通道完整輸出特征圖。
3×3卷積映射如圖4(b)所示。以步長為3將PE陣列劃分為4組,同一列的組處理相同輸入特征圖,同一行的組處理相同輸出特征圖。該陣列可并行計(jì)算2 通道輸入、2 通道輸出。每組內(nèi)3 行PE 分別計(jì)算同一輸入特征圖通道內(nèi)的3 個卷積窗口,行內(nèi)每個PE 并行計(jì)算卷積窗口內(nèi)3 個乘法。為簡化控制邏輯,每列PE 數(shù)據(jù)都是廣播寫入,因此,緩存內(nèi)寫入數(shù)據(jù)都相同。根據(jù)PE位置的不同,卷積時按不同的順序使用緩存內(nèi)數(shù)據(jù)。PE 內(nèi)有3 個輸入特征圖局部緩存,最多可緩存3 行輸入特征圖,實(shí)現(xiàn)3×3 卷積行間數(shù)據(jù)的復(fù)用。
圖4 PE 陣列映射示意圖Fig.4 PE array mapping diagram
圖5 展示了PE 組Group(0,0)計(jì)算步長為1 的3×3 卷積時的過程。計(jì)算卷積第1 行時,該行的卷積核固定,在#0 時刻這9 個PE 可計(jì)算出前3 個卷積結(jié)果的中間值。5 個周期后完成該行輸入特征圖計(jì)算,切換到第2 行卷積核與第2 行輸入特征圖相乘,第3 行執(zhí)行相同步驟。分割位寬16 的特征圖經(jīng)核大小為3、步長為1 的卷積后有效數(shù)據(jù)只有14 個,因此,#4 時刻會有一項(xiàng)無效數(shù)據(jù)。3 行特征圖乘積共15 個周期,中間值疊加后即得到完整的一行14 個卷積結(jié)果。卷積過程中的3 行輸入特征圖在PE 內(nèi)分3 片局部緩存存放,除卷積開始前需要提前加載3 行數(shù)據(jù),計(jì)算下一行卷積時,只需要將第1 行輸入數(shù)據(jù)替換成第4 行輸入數(shù)據(jù),即可減少片內(nèi)數(shù)據(jù)的重復(fù)傳輸。
從圖5 可以看出,每行PE 計(jì)算時進(jìn)行了不同的映射,如在#0 時刻時,第1 個卷積窗口的數(shù)據(jù)D(0,0)、D(0,1)、D(0,2)分配到PE(0,0)、PE(0,1)、PE(0,2),而第2個卷積窗口的數(shù)據(jù)D(0,1)、D(0,2)、D(0,3)則分配到PE(1,1)、PE(1,2)、PE(1,0)。兩個卷積窗口間是彼此重疊的,PE(0,1)與PE(1,1)、PE(0,2)與PE(1,2)以及PE(1,0)與下一時刻的PE(0,0)使用的是相同的數(shù)據(jù)。使用該方法排序后,同一列PE使用的是相同的輸入特征圖,數(shù)據(jù)傳輸變得非常規(guī)則,可簡化PE陣列的互連與控制、同時減少PE內(nèi)部局部緩存的大小。針對卷積步長為2 的運(yùn)算,橫向上數(shù)據(jù)流向不做調(diào)整,后續(xù)模塊可通過數(shù)據(jù)有效信號過濾無效數(shù)據(jù),而縱向上修改輸入特征圖的數(shù)據(jù)請求邏輯,當(dāng)每個卷積窗口計(jì)算完時共替換兩行數(shù)據(jù),減少數(shù)據(jù)計(jì)算量。若是進(jìn)行四周補(bǔ)零后再卷積的運(yùn)算,數(shù)據(jù)請求時在輸入特征圖局部緩存首位加入數(shù)據(jù)0,即行首補(bǔ)零,而行末補(bǔ)零乘積結(jié)果為0,通過禁用該列PE 實(shí)現(xiàn),即拉低該列PE 使能信號。卷積過程中首尾兩行補(bǔ)零行不寫入輸入特征圖局部緩存,調(diào)整緩存讀出控制減少計(jì)算量,疊加卷積中間值時也少疊加一次。
圖5 PE 陣列組內(nèi)卷積計(jì)算過程Fig.5 Convolution calculation process in PE array group
2.2.3 局部池化運(yùn)算單元設(shè)計(jì)
池化是一種降采樣操作,常用于提取特征信息和縮小特征圖尺寸,常見有平均池化和最大池化。以最大池化為例,局部池化運(yùn)算單元設(shè)計(jì)如圖6所示,其中,左半部分用于當(dāng)前行數(shù)據(jù)比較,右半部分用于完成多行數(shù)據(jù)比較及復(fù)用,支持2×2 和3×3 兩種大小池化窗口。2×2 池化時,池化窗口間沒有重疊,每兩周期進(jìn)行一次比較。第1 行比較時,數(shù)據(jù)較大者直接壓入FIFO。當(dāng)下一行數(shù)據(jù)兩兩比較后,再讀出FIFO 中的值進(jìn)行比較,即可完成一個池化窗口的運(yùn)算,然后比較數(shù)據(jù)直接寫入輸出緩存模塊,并清空FIFO。3×3 池化時,增加下方通路比較第3 個數(shù)據(jù)與前兩個數(shù)據(jù)的較大者,將結(jié)果壓入FIFO。計(jì)算完池化窗口第3 行后,輸出當(dāng)前池化結(jié)果,并將第3 行的比較結(jié)果寫入FIFO。由于3×3 池化存在數(shù)據(jù)重疊,因此計(jì)算下一行池化窗口可直接從第2 行數(shù)據(jù)開始請求,并復(fù)用FIFO 中的結(jié)果,減少計(jì)算量和片內(nèi)數(shù)據(jù)的重復(fù)傳輸。使用此結(jié)構(gòu)進(jìn)行局部池化,每通道輸入特征圖只需要請求一次。此外,若池化時輸入特征圖尺寸除不盡,結(jié)果需要向上取整,即輸入特征圖的右側(cè)與下側(cè)需要補(bǔ)零,此時通過控制Valid 信號,填充數(shù)據(jù)0 到運(yùn)算單元中以完成一次完整的池化。
圖6 池化模塊Fig.6 Pooling module
2.2.4 訪存控制與片內(nèi)緩存設(shè)計(jì)
加速器使用更大的片內(nèi)緩存可以減少片外訪存需求,提高系統(tǒng)能效。但由于CNN 的特征圖、參數(shù)量大,限于面積、功耗的成本,因此片內(nèi)緩存不能設(shè)計(jì)太大。為適應(yīng)不同大小的特征圖并實(shí)現(xiàn)高效的并行運(yùn)算,設(shè)計(jì)如圖7所示結(jié)構(gòu)對數(shù)據(jù)進(jìn)行分塊,其中,(i,j,c)表示第c通道第i行第j列數(shù)據(jù)。讀寫時特征圖以8 通道、寬度16 進(jìn)行分組,并以行方向、列方向、通道方向的順序進(jìn)行連續(xù)讀寫。由于3×3卷積、3×3 池化以及同時進(jìn)行卷積與池化時存在數(shù)據(jù)重疊,因此分塊時需要根據(jù)情況重復(fù)讀取部分?jǐn)?shù)據(jù)。
圖7 特征圖分塊示意圖Fig.7 Block diagram of feature map
卷積神經(jīng)網(wǎng)絡(luò)運(yùn)算中需要頻繁讀取大量的數(shù)據(jù),為降低加速器與片外存儲器間讀寫耗時的感知,片內(nèi)緩存采用乒乓結(jié)構(gòu)。如圖8所示,輸入和輸出緩存均由兩塊緩存組成,通過重疊讀寫操作和數(shù)據(jù)運(yùn)算時間,增加訪存吞吐量。對于輸入緩存,當(dāng)其中一塊保存的數(shù)據(jù)徹底使用完畢且另一塊寫入一組完整數(shù)據(jù)塊后,交換兩塊緩存使用權(quán),而輸出緩存中還存在卷積得到的部分和數(shù)據(jù),需要在計(jì)算下一數(shù)據(jù)塊時讀出疊加。因此,在最終結(jié)果寫滿一塊緩存且另一塊緩存數(shù)據(jù)完全寫入片外存儲后,才切換輸出緩存。
圖8 乒乓緩存示意圖Fig.8 Schematic diagram of Ping-Pong cache
輸入特征圖經(jīng)上述方法分塊后,若卷積層中包含所有通道的數(shù)據(jù)塊能夠存在一塊輸入緩存,則緩存中數(shù)據(jù)可以多次使用。輸入緩存所有通道數(shù)據(jù)遍歷一次后無需切換到另一塊緩存,也無需從片外存儲重新讀取,直到輸出特征圖所有通道計(jì)算完成。若包含所有通道的數(shù)據(jù)塊能夠在兩塊輸入緩存內(nèi)存下,則可在兩塊緩存間切換以完成所有通道輸出特征圖的計(jì)算,也不需要從片外存儲反復(fù)讀取相同數(shù)據(jù)。
為保證有足夠的數(shù)據(jù)滿足運(yùn)算單元的需求,輸入輸出緩存包括多個讀寫端口。如圖9所示,每塊片內(nèi)緩存拆分為16 片并列的RAM 緩存區(qū),緩存區(qū)數(shù)量與運(yùn)算單元相關(guān)。緩存區(qū)使用相同地址訪問以簡化緩存讀寫邏輯。片外存儲讀寫時將16 片緩存區(qū)分為兩組,每次并行寫入8 片輸入緩存區(qū),從8 片輸出緩存區(qū)并行讀出。
圖9 片內(nèi)緩存示意圖Fig.9 Schematic diagram of on-chip cache
不同的運(yùn)算操作加速器內(nèi)數(shù)據(jù)流向和緩存存儲數(shù)據(jù)的順序不同。進(jìn)行1×1 卷積時PE 陣列可以并行計(jì)算16 通道特征圖,因此,當(dāng)輸入緩存寫完8 通道上述特征圖數(shù)據(jù)塊后,下一數(shù)據(jù)塊寫入另一組8 片緩存區(qū)中,保證16 通道的輸出。如果加速器同時完成卷積和池化運(yùn)算,激活模塊輸出16 通道的輸出特征圖后,流向局部池化模塊,通過16 個池化運(yùn)算單元并行完成池化操作,然后并行寫入輸出緩存。回寫片外緩存時輸出緩存中數(shù)據(jù)的讀出順序與寫入輸入緩存相同。3×3 卷積時,每組緩存區(qū)存滿完整通道的數(shù)據(jù)后才切換至另一組緩存區(qū)。PE 陣列每次最多并行計(jì)算5 通道特征圖,8 片緩存區(qū)分成兩次進(jìn)行。與1×1 卷積不同,PE 陣列中每三列PE 的數(shù)據(jù)都由同一片緩存區(qū)提供。3×3 卷積時PE 陣列每次最多輸出5 通道數(shù)據(jù),若數(shù)據(jù)流向池化模塊,最多也只會同時使用5 個池化運(yùn)算單元。輸出緩存的寫入也同樣是分兩次寫入8 通道特征圖數(shù)據(jù),寫滿完整通道的數(shù)據(jù)后切換至另一組緩存區(qū)。
只進(jìn)行局部池化時輸入特征圖不進(jìn)行量化,輸入緩存占用較大,當(dāng)輸入數(shù)據(jù)過大時可使用兩片緩存區(qū)進(jìn)行存儲。從輸入緩存讀取8 通道數(shù)據(jù),并行完成池化運(yùn)算后,直接寫入輸出緩存。經(jīng)局部池化后的數(shù)據(jù)縮小了4 倍,輸出緩存的寫入順序與3×3 卷積相同,寫滿完整通道的數(shù)據(jù)后切換至另一組緩存區(qū)。而全局池化層常位于CNN 的最后一層,此時的特征圖尺寸小、通道多,并且每通道輸入都被轉(zhuǎn)化為1×1 輸出。因此,采用與1×1 卷積相同的讀寫順序,同時從輸入緩存讀出16 通道數(shù)據(jù),運(yùn)算完成后數(shù)據(jù)同樣并行寫入16 片輸出緩存區(qū)。
對本文設(shè)計(jì)的RISC-V 架構(gòu)卷積神經(jīng)網(wǎng)絡(luò)專用指令集處理器進(jìn)行驗(yàn)證測試。首先在軟件層面上完成對定制的CNN 拓展指令的實(shí)現(xiàn)和驗(yàn)證。然后調(diào)用拓展指令完成SqueezeNet網(wǎng)絡(luò)分類算法的程序編程。通過仿真工具仿真處理器加速卷積神經(jīng)網(wǎng)絡(luò)計(jì)算的過程,完成處理器的功能驗(yàn)證。最后在FPGA 平臺上實(shí)現(xiàn),對系統(tǒng)資源占用、功耗、性能等進(jìn)行評估。
本文設(shè)計(jì)的CNN 拓展指令采用匯編指令的形式嵌入到C 語言程序中,取代CNN 算法中的耗時操作以達(dá)到加速目的[17]。通過指定格式在C 語言代碼中將拓展指令的匯編語句嵌入,指定傳入的數(shù)據(jù)、通用寄存器,最后編譯成相應(yīng)的RISC-V 指令。完成算法程序編寫后,使用RISC-V 交叉編譯工具鏈進(jìn)行編譯,生成程序的二進(jìn)制文件。
將本文使用的FPGA 驗(yàn)證平臺為含Xilinx Kintex-7系列FPGA 芯片的Genesys 2 開發(fā)板。將處理器工作頻率約束在100 MHz,經(jīng)Vivado 軟件綜合以及布局布線后,F(xiàn)PGA 內(nèi)部資源使用情況如表3所示,處理器建立時間裕度為0.189 ns,片上功耗為1.966 W,其中動態(tài)功耗占91%。
表3 FPGA 資源使用情況Table 3 FPGA resource utilization
不同卷積神經(jīng)網(wǎng)絡(luò)模型的結(jié)構(gòu)各異,其計(jì)算的結(jié)果可能相差很大。為更好地對本文設(shè)計(jì)的處理器進(jìn)行資源和性能評估,此處選用推理相同網(wǎng)絡(luò)的文獻(xiàn)進(jìn)行對比,如表4所示。因?yàn)楸疚奶幚砥髅嫦蛭锫?lián)網(wǎng)終端和移動端設(shè)備,考慮到低成本、低功耗的限制,使用了較小規(guī)模的PE 陣列、片上緩存,資源消耗較少。相較于文獻(xiàn)[18],雖然推理計(jì)算速度上沒有那么快,但是本文設(shè)計(jì)具有更好的性能功耗比,提高約25.81%,同時也優(yōu)于其他對比處理器。
表4 FPGA 平臺加速器性能對比Table 4 Performance comparison of FPGA accelerators
本文處理器與常見通用處理器、GPU 和手機(jī)處理器推理計(jì)算SqueezeNet 網(wǎng)絡(luò)模型的性能對比如表5所示,其中,AMD Ryzen7 3700X 與英偉達(dá)RTX2070 Super 均在Caffe 框架下計(jì)算,驍龍835 則在為手機(jī)端優(yōu)化的推理框架NCNN 下計(jì)算。由于輕量化卷積神經(jīng)網(wǎng)絡(luò)前向推理過程的計(jì)算量和參數(shù)量對RTX2070 Super 來說負(fù)載較小,并不能充分利用內(nèi)部所有運(yùn)算單元,因此實(shí)際功耗有所下降。通過對比可知,在相同卷積神經(jīng)網(wǎng)絡(luò)模型推理上,在FPGA 上實(shí)現(xiàn)的本文處理器比驍龍835 單核計(jì)算耗時減少40.64%,且性能功耗比是通用CPU Ryzen7 3700X 的25.39 倍、GPU RTX2070 Super 的1.04 倍、手機(jī)處理器驍龍835 單核計(jì)算時的3.05 倍、四核計(jì)算時的1.16 倍。
表5 不同平臺性能對比Table 5 Performance comparison of different platforms
本文基于開源指令集RISC-V 設(shè)計(jì)卷積神經(jīng)網(wǎng)絡(luò)專用指令集處理器。面向物聯(lián)網(wǎng)應(yīng)用場景,針對輕量化網(wǎng)絡(luò)模型的基本運(yùn)算操作定制RISC-V 拓展指令。同時考慮物聯(lián)網(wǎng)設(shè)備的算力與資源限制,對加速器采用量化網(wǎng)絡(luò)模型、優(yōu)化運(yùn)算單元、靈活調(diào)整數(shù)據(jù)通路、設(shè)計(jì)相應(yīng)數(shù)據(jù)結(jié)構(gòu)和片上緩存等方法設(shè)計(jì)加速方案?;贔PGA 平臺的實(shí)驗(yàn)結(jié)果表明,在100 MHz 工作頻率下推理SqueezeNet 網(wǎng)絡(luò),處理器計(jì)算性能達(dá)到19.08 GOP/s,功耗為1.966 W,比手機(jī)處理器單核計(jì)算速度更快,并且在性能功耗比上較其他平臺更具優(yōu)勢。下一步將針對具體應(yīng)用對主處理器核心進(jìn)行深度定制,開發(fā)相應(yīng)的編譯器,同時使用高級程序語言提高使用效率,保證軟件兼容性。