龔鳴清 葉煌 張鑒 盧興敬 陳偉
摘 要:針對使用ARM處理器的移動智能設(shè)備執(zhí)行神經(jīng)網(wǎng)絡(luò)推理計(jì)算效率不高的問題,提出了一套基于ARMv8架構(gòu)的單精度浮點(diǎn)通用矩陣乘法(SGEMM)算法優(yōu)化方案。首先,確定ARMv8架構(gòu)的處理器執(zhí)行SGEMM算法的計(jì)算效率受限于向量化計(jì)算單元使用方案、指令流水線和緩存未命中的發(fā)生概率;其次,針對三點(diǎn)導(dǎo)致計(jì)算效率受限的原因?qū)崿F(xiàn)向量指令內(nèi)聯(lián)匯編、數(shù)據(jù)重排和數(shù)據(jù)預(yù)取三條優(yōu)化技術(shù);最后,根據(jù)語音方向的神經(jīng)網(wǎng)絡(luò)中常見的三種矩陣模式設(shè)計(jì)測試實(shí)驗(yàn),實(shí)驗(yàn)中使用RK3399硬件平臺運(yùn)行程序。實(shí)驗(yàn)結(jié)果表示:方陣模式下單核計(jì)算速度為10.23GFLOPS,達(dá)到實(shí)測浮點(diǎn)峰值的78.2%;在細(xì)長矩陣模式下單核計(jì)算速度為6.35GFLOPS,達(dá)到實(shí)測浮點(diǎn)峰值的48.1%;在連續(xù)小矩陣模式下單核計(jì)算速度為2.53GFLOPS,達(dá)到實(shí)測浮點(diǎn)峰值19.2%。將優(yōu)化后的SGEMM算法部署到語音識別神經(jīng)網(wǎng)絡(luò)程序中,程序的實(shí)際語音識別速度取得了顯著提高。
關(guān)鍵詞:ARMv8;單指令多數(shù)據(jù)流計(jì)算;基礎(chǔ)線性代數(shù)子程序庫;高性能計(jì)算
中圖分類號: TP332控制器和處理器
文獻(xiàn)標(biāo)志碼:A
Abstract: Aiming at the inefficiency of neural network inferential calculation executed by mobile intelligent devices using ARM processor, a set of Single precision floating GEneral Matrix Multiply (SGEMM) algorithm optimization scheme based on ARMv8 architecture was proposed. Firstly, it was determined that the computational efficiency of the processor based on ARMv8 architecture executing SGEMM algorithm was limited by the vectorized computation unit usage scheme, the instruction pipeline, and the probability of occurrence of cache miss. Secondly, three optimization techniques: vector instruction inline assembly, data rearrangement and data prefetching were implemented for the three reasons that the computational efficiency was limited. Finally, the test experiments were designed based on three matrix patterns commonly used in the neural network of speech direction and the programs were run on the RK3399 hardware platform. The experimental results show that, the single-core computing speed is 10.23GFLOPS in square matrix mode, reaching 78.2% of the measured floating-point peak value; the single-core computing speed is 6.35GFLOPS in slender matrix mode, reaching 48.1% of the measured floating-point peak value; and the single-core computing speed is 2.53GFLOPS in continuous small matrix mode, reaching 19.2% of the measured floating-point peak value. With the optimized SGEMM algorithm deployed into the speech recognition neural network program, the actual speech recognition speed of program is significantly improved.
Key words: ARMv8; single instruction multiple data; basic linear algebra subprogram; high performance computation
0 引言
近年由Intel公司創(chuàng)始人摩爾提出的摩爾定律已經(jīng)逐漸在以X86-64指令集為代表的復(fù)雜指令集(Complex Instruction Set Computer, CISC)型中央處理器(Central Processing Unit, CPU)上失效,而以ARM為首的精簡指令集(Reduced Instruction Set Computer, RSIC)型CPU則隨著智能時代的到來進(jìn)入了超高速發(fā)展期。ARM公司于2014年1月正式發(fā)布了首個64位架構(gòu)ARMv8-A,ARMv8-A新加入數(shù)種特性,例如:更大的尋址范圍、數(shù)量更多位數(shù)更寬的通用寄存器組、并發(fā)執(zhí)行浮點(diǎn)計(jì)算的128b NEON向量單元、復(fù)合單指令多數(shù)據(jù)流(Single Instruction Multiple Data, SIMD)計(jì)算指令。
高性能計(jì)算在桌面與服務(wù)器端CPU和其他大體積大功耗的高性能計(jì)算設(shè)備上是一個常見的研究課題,早在幾十年前第一臺通用計(jì)算機(jī)ENIAC誕生的時候,它承擔(dān)的任務(wù)就是替美國軍方高效計(jì)算彈道,從數(shù)學(xué)模型的角度來看就是對一系列復(fù)雜的線性方程組進(jìn)行近似求解,而求解過程也是通過一系列復(fù)雜的線性代數(shù)計(jì)算來實(shí)現(xiàn)的。時至今日,雖然通用計(jì)算機(jī)和中央處理器的性能可以滿足普通用戶的需求,但是在執(zhí)行線性代數(shù)計(jì)算的時候依然還是要依賴于對應(yīng)平臺的基礎(chǔ)線性代數(shù)子程序庫(Basic Linear Algebra Subprograms, BLAS),針對目標(biāo)硬件優(yōu)化的BLAS庫允許計(jì)算設(shè)備高效率的執(zhí)行線性代數(shù)計(jì)算,著名的BLAS庫有:AMD的ACML[1]、IBM的ESSL[2]、NVIDIA的CUBLAS[3]、TACC的GotoBLAS[4-5]、 中國科學(xué)院計(jì)算技術(shù)研究所的OpenBLAS[6]。
本文旨在提高移動智能設(shè)備上神經(jīng)網(wǎng)絡(luò)推理計(jì)算的執(zhí)行效率,推理計(jì)算的執(zhí)行過程中會大量調(diào)用單精度浮點(diǎn)通用矩陣乘法(Single precision floating GEneral Matrix Multiply, SGEMM)算法,所以面向Cortex-A72架構(gòu)進(jìn)行SGEMM優(yōu)化,測試平臺為RK3399,實(shí)驗(yàn)參照對象為OpenBLAS庫的0.3.4版本。因?yàn)镺penBLAS庫為跨多平臺的開源項(xiàng)目,在公司的產(chǎn)品和實(shí)驗(yàn)室研究課題中有著廣泛的應(yīng)用[7],選取OpenBLAS作為參考對象更具備說服力。
首先根據(jù)GotoBLAS[4]的思路,實(shí)現(xiàn)SGEMM的計(jì)算子任務(wù)劃分;其次,使用Cortex-A72架構(gòu)特性[8]實(shí)現(xiàn)計(jì)算核心代碼,用于執(zhí)行劃分后的計(jì)算子任務(wù);最后,將不同的計(jì)算核心與數(shù)據(jù)重排方案匹配不同的矩陣規(guī)模。與OpenBLAS對比的實(shí)驗(yàn)結(jié)果為(以下為行文方便,本文實(shí)現(xiàn)的SGEMM為Evalite_SGEMM,OpenBLAS實(shí)現(xiàn)的SGEMM為OpenBLAS_SGEMM):方陣模式下,Evalite_SGEMM相較于OpenBLAS_SGEMM性能提升了170%,達(dá)到了實(shí)測峰值的78.2%;細(xì)長矩陣模式下,Evalite_SGEMM相較于OpenBLAS_SGEMM性能提升了312%,達(dá)到了實(shí)測峰值的48.1%;連續(xù)小矩陣模式下,Evalite_SGEMM相較于OpenBLAS_SGEMM性能提升了283%,達(dá)到了實(shí)測峰值的19.2%。
1 基礎(chǔ)介紹
1.1 Cortex-A72處理器介紹
圖1是ARM官方網(wǎng)站上展示的Cortex-A72處理器的總體架構(gòu)。從圖1可知,Cortex-A72同時兼容32b/64b指令集,處理器內(nèi)置48KB的3路組相連L1指令cache、32KB的二路組相連L1級數(shù)據(jù)緩存(D-cache)和512KB到4MB的16路組相連L2數(shù)據(jù)共享緩存(D-share_cache),一個集成電路板上集成1到4個Cortex-A72核心,核心之間通過AMBA(Advanced Microcontroller Bus Architecture)相連。Cortex-A72處理器采用臺積電16nm FinFET+制程,使得核心主頻最高可達(dá)到2.5GHz。Cortex-A72采用的是3發(fā)射超標(biāo)量亂序流水線,每個核心內(nèi)設(shè)32個128b浮點(diǎn)寄存器v0~v31專門用于SIMD計(jì)算指令。
Sogou_SGEMM是移動智能設(shè)備上深度學(xué)習(xí)框架的基礎(chǔ)數(shù)學(xué)庫組成部分,以機(jī)器翻譯框架為例,其中一個關(guān)鍵組成部分被稱為轉(zhuǎn)導(dǎo)模型[9],轉(zhuǎn)導(dǎo)模型包含多種規(guī)格的SGEMM計(jì)算任務(wù)。針對語音方向深度學(xué)習(xí)框架中常用或者效率受限的3種矩陣規(guī)模進(jìn)行調(diào)優(yōu):方陣(M=O=N)、細(xì)長陣(M=2、4,O=256,N=30000)、迷你矩陣(M≤16,O=64,N≤16)。
實(shí)現(xiàn)思路如下所述:第一步,實(shí)現(xiàn)兩個高度優(yōu)化的計(jì)算核心子函數(shù)SGEBP與SGEPD,旨在CPU運(yùn)行這兩個子函數(shù)時指令流水線更密集,同時更少地發(fā)生控制冒險(xiǎn)、數(shù)據(jù)冒險(xiǎn)[10];第二步,重排A、B、C三個矩陣的數(shù)據(jù)存儲順序,使得矩陣的數(shù)據(jù)存儲順序符合SGEBP和SGEPDOT在執(zhí)行計(jì)算循環(huán)體時的連續(xù)讀寫順序;第三步,劃分A、B、C三個矩陣,使得SGEBP和SGEPD在計(jì)算一塊子區(qū)域時,數(shù)據(jù)在cache與主存之間的流通次數(shù)降到最低,降低讀寫操作帶來的額外時間開銷。
2 優(yōu)化實(shí)現(xiàn)
大規(guī)模矩陣計(jì)算的第一步是子區(qū)域分割,GotoBLAS[4]中提出的劃分方案總結(jié)并分析了全部情況,所以本文的研究重心是如何利用Cortex-A72架構(gòu)的特性,提升子任務(wù)計(jì)算內(nèi)核代碼的效率[11]。
2.1 內(nèi)聯(lián)匯編
參照1.1節(jié)可知,Cortex-A72的理論流水線為3發(fā)射超標(biāo)量亂序,圖2為Cortex-A72的流水線架構(gòu)圖。Cortex-A72的每1條指令在有序超標(biāo)量下經(jīng)過取指、譯碼、重命名后被亂序分派到各個執(zhí)行單元上完成指令期望的操作,在不用考慮數(shù)據(jù)相關(guān)性的前提下,流水線可以在每一個cycle中同時執(zhí)行3次整數(shù)計(jì)算、2次向量計(jì)算、1次分支跳轉(zhuǎn)、1次讀取和1次寫回中的任意3條[12]。此外Cortex-A72中內(nèi)置了2個SIMD計(jì)算單元NEON,NEON最初引入的目的是提高視頻和音頻的解碼速度。發(fā)展到ARMv8架構(gòu),內(nèi)置32個128b浮點(diǎn)寄存器,訪存部件支持128b單步讀寫,因此本文利用NEON單元
進(jìn)行SIMD計(jì)算加速。本文的實(shí)現(xiàn)采用的是GNU與LLVM都支持的內(nèi)聯(lián)匯編語法結(jié)構(gòu),在C程序中調(diào)用手動編寫的匯編代碼塊。
內(nèi)聯(lián)匯編要面向的是兩個不同的計(jì)算內(nèi)核SGEBP和SGEPDOT,其計(jì)算模式分別如圖3 (a)、(b)所示,圖中M1、N1、O1、M2、N2、O2分別為各個矩陣的橫縱軸,同形狀點(diǎn)表示的是一次內(nèi)聯(lián)匯編循環(huán)A、B、C涉及到的數(shù)據(jù),其中A、B的點(diǎn)只表示源操作數(shù),而C的點(diǎn)既表示源操作數(shù)也表示目的操作數(shù)。A的行和B的列坐標(biāo)分別對應(yīng)的是C的行和列坐標(biāo),所以SGEBP和SGEPDOT計(jì)算模式可分別表示為式(2)~(3):
SGEBP是沿著矩陣B1的N1軸進(jìn)行內(nèi)循環(huán),使得A1上的一個點(diǎn)跟B1上對應(yīng)的一整行均相乘,相乘的結(jié)果再累加到對應(yīng)的C1上一行,然后外層迭代A1沿著O1軸換到下一個點(diǎn),B1沿著O1軸換到下一行,C1保持行號不變但返回到行首第一個點(diǎn),當(dāng)對整個O1軸都迭代1次之后,C1的一行計(jì)算就全部完成了;SGEPDOT是沿著矩陣B2的O2軸進(jìn)行內(nèi)循環(huán),A2上列號與B2上行號對應(yīng)的點(diǎn)相乘再累加到對應(yīng)的C2上一點(diǎn),然后外層迭代A2回到當(dāng)前行行首,B2沿著N2軸切換到下一列,C2沿著N2軸切換到下一個點(diǎn),當(dāng)對整個N2軸都迭代一次之后,C2的一行就全部計(jì)算完成了。
上述模式屬于點(diǎn)對點(diǎn)計(jì)算,利用NEON向量化指令進(jìn)行計(jì)算是優(yōu)化的第一個目標(biāo),所以需要將點(diǎn)對點(diǎn)計(jì)算組合成向量計(jì)算,{fmla v0.4s,v1.4s,v2.s[0]},這條指令的功能為v2寄存器上的1個單精度浮點(diǎn)數(shù)分別乘上v1寄存器上的4個單精度浮點(diǎn)數(shù),再累加到v0寄存器的4個單精度浮點(diǎn)數(shù)上,其中v0和v1的4個單精度浮點(diǎn)數(shù)從位高到低一一對應(yīng)。fmla意味著arm可以做到1條指令進(jìn)行8次浮點(diǎn)計(jì)算,符合矩陣乘法計(jì)算公式的基礎(chǔ)操作,所以內(nèi)聯(lián)匯編將圍繞著fmla展開,而使用fmla作為基本計(jì)算操作下,SGEBP和SGEPDOT的計(jì)算模式都要進(jìn)行一定程度的修改, 如圖4(a)、(b)所示。圖中A3、B3、C3、A4、B4、C4分別是SGEBP和SGEPDOT一次內(nèi)循環(huán)所需要的數(shù)據(jù),但是利用NEON執(zhí)行單元后,1條fmla指令同時計(jì)算矩陣B、C內(nèi)的4個單精度浮點(diǎn)數(shù)。SGEBP模式A3上一個點(diǎn)乘以B3上一個向量再累加到C3上一個向量,直到B3一整行數(shù)據(jù)都跟A3上同一個點(diǎn)完成乘法計(jì)算并累加到C3一整行上,A3沿著橫軸切換到下個點(diǎn),B3沿著縱軸向切換到下一行,當(dāng)整個B3都累加到C3同一行上,標(biāo)志著C3這一行上的計(jì)算完全結(jié)束;SGEPDOT模式變?yōu)锳4上縱軸4個點(diǎn)為1個向量取出,B4上橫軸4個點(diǎn)為1個向量取出,然后展開4次fmla計(jì)算,并依次再累加到C4的4個向量上,然后A4沿著橫軸切換到下一個向量上,B4沿著縱軸切換到下一個向量,循環(huán)計(jì)算,當(dāng)A4沿著橫軸循環(huán)到底,B4沿著縱軸循環(huán)到底,C4上4個向量的計(jì)算完全結(jié)束。
在確定了使用fmla作為主要的向量計(jì)算指令后,接下來研究的就是fmla在什么狀態(tài)下才可以讓流水線滿排。這里本文參考了arm公司的《Cortex-A72優(yōu)化指南》,指南里對Cortex-A72的各種指令的執(zhí)行參數(shù)進(jìn)行了一一列舉,從指南里可以得知fmla指令在128b格式下單條的執(zhí)行延遲為7個cycle,Cortex-A72有2個SIMD執(zhí)行部件,并行執(zhí)行延遲為3個cycle,理想的吞吐量為每個cycle完成1條fmla指令。且文檔里特別說明了,混合計(jì)算指令(乘加、乘減等)實(shí)際執(zhí)行的時候是將混合指令拆分成乘法、加法兩條來執(zhí)行,所以混合計(jì)算指令的理論峰值吞吐量為每個cycle執(zhí)行1條。
為了驗(yàn)證文檔里數(shù)據(jù)的正確性,以及驗(yàn)證NEON執(zhí)行指令時數(shù)據(jù)相關(guān)性,參考《Cortex-A72優(yōu)化指南》設(shè)計(jì)峰值測試實(shí)驗(yàn),結(jié)果為峰值下每1.167個cycle完成1條fmla,循環(huán)展開3條以上目的寄存器不同的fmla下就可達(dá)到浮點(diǎn)峰值,與指南中給出的每cycle完成1條的結(jié)果存在16%的偏差,但測試結(jié)果顯示NEON的單精度向量計(jì)算指令的數(shù)據(jù)相關(guān)性帶來的延遲為4cycle,與指南中給出的數(shù)據(jù)一致。對于實(shí)測峰值為13.2GFLOPS,而理論峰值為14.4GFLOPS的狀況,在與測評平臺的系統(tǒng)設(shè)計(jì)工程師溝通分析后認(rèn)為,這是由于底層的功耗調(diào)度驅(qū)動對處理器的性能進(jìn)行了限制,所以測試程序?qū)嶋H上是在功耗受限的處理器上運(yùn)行。
至此結(jié)合每個浮點(diǎn)寄存器可保存4個單精度浮點(diǎn)數(shù)的條件,想要匯編代碼塊在執(zhí)行的時候SIMD單元利用率高,需要保證循環(huán)展開4條以上的目標(biāo)寄存器不同的fmla指令,即安排4個以上的浮點(diǎn)寄存器用于對矩陣C的訪存操作,但此點(diǎn)不適用于連續(xù)小矩陣乘模式的部分情況,因?yàn)樾【仃嚹J较翪本身規(guī)模太小用不滿4個浮點(diǎn)寄存器。
2.2 數(shù)據(jù)重排
2.1節(jié)是從計(jì)算指令的角度討論如何讓流水線滿排,而沒有考慮訪存指令在計(jì)算中的影響,事實(shí)上計(jì)算訪存比在BLAS優(yōu)化中同樣是一個需要的問題[13],因?yàn)楫?dāng)計(jì)算指令在流水線上達(dá)到足夠的密度后,訪存指令獲取數(shù)據(jù)的效率受到緩存未命中(cache miss)情況的限制,從而限制了計(jì)算指令的執(zhí)行效率[14]。本文的內(nèi)聯(lián)匯編計(jì)算核心在迭代執(zhí)行規(guī)模為4096×4096×4096的矩陣乘法時,浮點(diǎn)效率3.2GFLOPS,為理論峰值的22.2%。這是因?yàn)樵诘鶶GEBP或者SGEPDOT的時候需要循環(huán)多次讀取整個矩陣B,而本文測試使用的CPU L2 D-cache總量為512KB,當(dāng)B的規(guī)模增大到512KB以上時,每次循環(huán)讀取矩陣B的時候有一部分?jǐn)?shù)據(jù)并不在D-cache上,需要去主存上讀取,這部分?jǐn)?shù)據(jù)的讀取每一次都會產(chǎn)生cache miss,從而造成了計(jì)算效率嚴(yán)重下降,這是需要進(jìn)行數(shù)據(jù)重排和預(yù)取的第一個原因。
第二個原因依然是從訪存指令出發(fā),從高級語言的角度來看對于數(shù)據(jù)的操作是直接的,一套復(fù)合運(yùn)算用C語言書寫一行計(jì)算表達(dá)式就可以描述;但是從匯編的角度來看,計(jì)算指令在執(zhí)行之前需要把將要使用的變量讀到通用寄存器上,主存和cache上的數(shù)據(jù)必須經(jīng)過寄存器才能被CPU的執(zhí)行單元進(jìn)行操作,而由于數(shù)據(jù)相關(guān)性,在數(shù)據(jù)沒有被讀入寄存器之前,計(jì)算指令就不會執(zhí)行,剛才說到的cache miss是阻礙數(shù)據(jù)讀入寄存器的一個因素,而還有一個因素是執(zhí)行l(wèi)oad或者store指令時地址的變化。例如,在SGEPDOT里,load矩陣B的數(shù)據(jù)是如下格式{ldr v0,[base];add base,base,x0;},之所以要這么做,是因?yàn)锽的數(shù)據(jù)是跳行讀取的,x0是B的行字節(jié)寬度,在讀取一行上的某個向量之后,就需要手動計(jì)算地址來定位到下一行,這也是因?yàn)殡m然ARMv8支持寄存器間址尋址,但并不支持寄存器間址尋址后自動更新源地址,而相反的,如果是使用立即數(shù)間址尋址,是支持在尋址之后自動更新源地址的,也就是說如下兩個格式{ldr v0,[base,#imme]!},{ldr v0,[base,#imme];add base,base,#imme}完成的是一樣的功能,在使用的執(zhí)行單元數(shù)量和種類相同的情況下,前一種格式只需要1條指令,而后一種格式需要2條指令,且這2條指令之間存在數(shù)據(jù)相關(guān),即需要插入NOP來填塞流水線。
第三個原因從計(jì)算訪存比出發(fā),內(nèi)聯(lián)匯編代碼core為了代碼的簡潔性和泛化性,內(nèi)部實(shí)現(xiàn)一層循環(huán),例如SGEPDOT的一次需要沿著0軸循環(huán)256步,不可能把256步的每一步都寫成代碼,正確的做法是直接寫出8步或者16步的計(jì)算代碼,然后循環(huán)執(zhí)行32次或者16次。這就導(dǎo)致了一個問題,流水線想要循環(huán)執(zhí)行的過程中迅速進(jìn)入滿排,那么計(jì)算訪存比就必須足夠高,根據(jù)式(1)可知,最理想的情況為在循環(huán)體內(nèi)2次load就可以展開4次fmla。
綜合以上3點(diǎn),本文采取了以下重排方案來分別處理矩陣A與B、C。
圖5(a)是矩陣A、C的重排方案,(b)是矩陣B的重排方案,同形狀的點(diǎn)表示重拍前后同列和同行上的4個數(shù)據(jù)單元。對于A來說是將同列上4個數(shù)變?yōu)橥猩系刂愤B續(xù)的4個數(shù),也可以看作是局部上的矩陣轉(zhuǎn)置,但是無論是行還是列都必須以4的倍數(shù)進(jìn)行迭代的重排,實(shí)際情況下往往行列都存在余數(shù),那剩下的一部分并不進(jìn)行重排,因?yàn)榭紤]剩余部分的兼容性會導(dǎo)致程序的結(jié)構(gòu)變得復(fù)雜,且實(shí)際測試結(jié)果表明余數(shù)部分的重排并不會帶來性能上的明顯提升。而將A進(jìn)行圖5(a)所示的重排后,一次load就可以load原序里4個同列的點(diǎn),由矩陣乘法計(jì)算模型可知,這4個點(diǎn)對應(yīng)的B的數(shù)據(jù)也是相同的,換句話說就是對A進(jìn)行一次load,再對比B進(jìn)行一次load,就已經(jīng)可以展開4次目標(biāo)寄存器不同的fmla計(jì)算。對于B的重排則是進(jìn)一步地強(qiáng)化局部的計(jì)算訪存比,從圖5(b)可以看出對B的重排,是以1個向量為基本單位,將同列的4個向量變?yōu)橥猩系刂愤B續(xù)的4個向量,這樣2次load(ARMv8指令集支持連續(xù)地址連讀、連寫2個數(shù)據(jù)單元)就可以load 4個B上的向量,并與A的4個點(diǎn)(也可以看作為1個向量)展開16次fmla計(jì)算,且面對的是4個不同的目的寄存器,從而16次fmla可以充分利用2個SIMD單元。在SGEBP模式下,重排后的計(jì)算訪存比為2;在SGEPDOT模式下,重排后的計(jì)算訪存比為4;且兩種模式下訪存指令都可以在一定程度上被fmla指令覆蓋。
此外,重排可以沿著縱軸進(jìn)行延長或者縮短的。在方陣上A、B的重排可以沿著縱軸到底部的,而在2×256×30000的規(guī)模上,A只有2列,進(jìn)行的就是2×4規(guī)模的重排,同時細(xì)長矩陣模式下B的全列重排占據(jù)了一次完整計(jì)算98%的時間,為了減少B全列重排對計(jì)算效率的嚴(yán)重影響,對于細(xì)長矩陣模式的重排本文也作了一些變化。首先,B的重排是以4行為一個子區(qū)域進(jìn)行的;其次,B的重排結(jié)果在重排完成后進(jìn)行暫時性的保存,也就是說當(dāng)前計(jì)算完成之后,B重排后的并不只是用于最近的幾次計(jì)算,而是框架模型沒有進(jìn)行改動之前一直重復(fù)使用,這里利用了神經(jīng)網(wǎng)絡(luò)推理計(jì)算中參數(shù)矩陣為常數(shù)矩陣的特性,每次計(jì)算時都可能發(fā)生變動的是矩陣A與C,所以對B進(jìn)行一次重排之后,可以滿足一整次框架運(yùn)行的計(jì)算需求,甚至可以將常參數(shù)矩陣就按照重排之后的格式進(jìn)行長期存儲。同時對于方陣,本文作了一個細(xì)節(jié)上的優(yōu)化,由于A和C都要乘以標(biāo)量系數(shù),所以在進(jìn)行全局矩陣標(biāo)量點(diǎn)乘時,本身就是對A和C的一次遍歷,將這次遍歷融合到A和C重排上,在矩陣小于512KB的情況下有11.2%的加速效果。
2.3 數(shù)據(jù)預(yù)取
重排完成之后,內(nèi)聯(lián)匯編的計(jì)算順序和矩陣的數(shù)據(jù)排列順序達(dá)成一致,數(shù)據(jù)在cache上得到充分重用,但數(shù)據(jù)重排和子區(qū)域劃分考慮到的cache是L2 D-cache,對于L2數(shù)據(jù)cache來說能在計(jì)算中穩(wěn)定保存的子區(qū)域,在32KB 大小的L1 D-cache上并不可行。ARMv8提供了數(shù)據(jù)預(yù)取指令來進(jìn)一步解決高密度計(jì)算場景下的L1 D-cache miss問題,例如{prfm L1keep,[addr]}就是將接下來需要使用到的首地址為addr的數(shù)據(jù)預(yù)取到L1 D-cache中,keep的意思是指預(yù)取的這部分?jǐn)?shù)據(jù)將要接下來的時間內(nèi)進(jìn)行多次使用,L1 D-cache就不會輕易地將這部分預(yù)取的數(shù)據(jù)刷出,還有另外一種后綴為strm,strm的意思指的是預(yù)取的這部分?jǐn)?shù)據(jù)在接下來的一段時間內(nèi)只計(jì)算一次,這類的預(yù)取數(shù)據(jù)在計(jì)算結(jié)束之后就會被L1 D-cache優(yōu)先丟棄[15]。
使用數(shù)據(jù)預(yù)取指令需要注意3個問題:第一,預(yù)取指令的執(zhí)行時間通常會超過執(zhí)行訪存指令并且沒有發(fā)生cache miss情況下的時間,這是因?yàn)轭A(yù)取的數(shù)據(jù)一般是分布在L2、L3 D-cache、或者主存上,在預(yù)取數(shù)據(jù)的時候,至少發(fā)生1次cache miss,最多發(fā)生3次,所以使用預(yù)取指令的時候,要確保有足夠的計(jì)算指令掩蓋預(yù)取訪存延遲。第二,預(yù)取指令跟訪存指令使用相同的訪存執(zhí)行單元,預(yù)取訪存延遲為幾十個機(jī)器周期到上百個機(jī)器周期不等,為了保證當(dāng)前計(jì)算指令依賴的數(shù)據(jù)能夠提前準(zhǔn)備好,預(yù)取指令在指令流水線上要跟正常訪存指令保持一定間隔。第三,預(yù)取指令并不是將緊接的幾次計(jì)算指令所需要的數(shù)據(jù)預(yù)取到L1 D-cache中,這是因?yàn)锳RM的D-cache在設(shè)計(jì)上就考慮了空間局部性,假設(shè)當(dāng)前計(jì)算所使用到的數(shù)據(jù)其地址為base,那么從base到 base+x地址范圍內(nèi)的連續(xù)數(shù)據(jù)都已經(jīng)在L1 D-cache中了(其中x是根據(jù)當(dāng)前計(jì)算狀態(tài)在一定范圍內(nèi)動態(tài)變化的值),所以正在計(jì)算中使用到的數(shù)據(jù)地址為base,預(yù)取的數(shù)據(jù)地址為base+y,當(dāng)y≤x時,預(yù)取就起不到任何加速作用,根據(jù)目前平臺的實(shí)際測試,預(yù)取達(dá)到最好的加速效果,是預(yù)取base+320地址所指向的數(shù)據(jù)。
3 測試結(jié)果與分析
本文測試使用的硬件平臺為Rockchip公司生產(chǎn)的RK3399芯片,內(nèi)置2個Cortex-A72核心與4個Cortex-A53核心,在測試過程中只開啟一個Cortex-A72核心,并鎖定運(yùn)行頻率為1.8GHz,可計(jì)算得理論浮點(diǎn)峰值為14.4GFLOPS,由圖6的代碼實(shí)測峰值為13.2GFLOPS,考慮到芯片工藝、測試平臺系統(tǒng)等非相關(guān)性干擾因素,本文以實(shí)測峰值13.2GFLOPS為對比基準(zhǔn)。圖6展示了3項(xiàng)優(yōu)化工作累加之后與原始算法的計(jì)算性能對比結(jié)果。
從圖6可知,3項(xiàng)優(yōu)化工作中:對性能提升效果最大的數(shù)據(jù)重排,以4096×4096×4096規(guī)模為例,只累加向量化的版本浮點(diǎn)性能為3.27GFLOPS,累加向量化、數(shù)據(jù)重排實(shí)現(xiàn)的版本浮點(diǎn)性能為9.69GFLOPS,性能提升196%;其次是向量化,以4096×4096×4096規(guī)模為例,原始算法的浮點(diǎn)性能為2.19GFLOPS,只累加向量化的版本浮點(diǎn)性能為3.27GFLOPS,性能提升49%;最后是數(shù)據(jù)預(yù)取,以1024×1024×1024規(guī)模為例,累加向量化、數(shù)據(jù)重排的版本浮點(diǎn)性能為7.20GFLOPS,向量化、數(shù)據(jù)重排、數(shù)據(jù)預(yù)取實(shí)現(xiàn)全部累加的最終版本浮點(diǎn)性能為9.97GFLOPS,性能提升38%;最后,以4096×4096×4096規(guī)模為例,原始算法的浮點(diǎn)性能為2.19GFLOPS,最終版本的浮點(diǎn)性能為10.23GFLOPS,性能提升367%。
4 結(jié)語
本文面向ARMv8架構(gòu)提出了三種不同角度的SGEMM算法優(yōu)化方案,降低了移動智能設(shè)備上語音識別和機(jī)器翻譯框架推理計(jì)算的時間消耗。實(shí)驗(yàn)結(jié)果表明,優(yōu)化后的SGEMM算法在保證了計(jì)算精度前提下有效地提升了計(jì)算速度。未來的工作,還將考慮多線程優(yōu)化,從而進(jìn)一步提高對整個處理器的利用率,更好地降低語音識別和機(jī)器翻譯框架推理計(jì)算的時間消耗。
參考文獻(xiàn) (References)
[1] AMD. AMD Core Math Library (ACML) [EB/OL]. [2018-09-12]. http://developer. amd. com/acml. jsp.
[2] FILIPPONE S. The IBM parallel engineering and scientific subroutine library [C]// Proceedings of the 1995 International Workshop on Applied Parallel Computing, LNCS 1041. Berlin: Springer, 1995: 199-206.
[3] QUINTANA-ORTI E S, IGUAL F D, CASTILLO M, et al. Evaluation and tuning of the level 3 CUBLAS for graphics processors [C]// Proceedings of the 2008 IEEE International Symposium on Parallel and Distributed Processing Symposium. Piscataway, NJ: IEEE, 2008: 1-8.
[4] GOTO K, van der GEIJN R A. Anatomy of high-performance matrix multiplication [J]. ACM Transactions on Mathematical Software, 2008, 34(3): Article No. 12.
[5] 蔣孟奇,張?jiān)迫?,宋剛,?GOTOBLAS一般矩陣乘法高效實(shí)現(xiàn)機(jī)制的研究[J].計(jì)算機(jī)工程,2008,34(7):84-86,103.(JIANG M Q, ZHANG Y Q, SONG G, et al. Research on high performance implementation mechanism of GOTOBLAS general matrix-matrix multiplication [J]. Computer Engineering, 2008, 34(7): 84-86, 103.)
[6] 張先軼,王茜,張?jiān)迫?OpenBLAS:龍芯3A CPU的高性能BLAS庫[J].軟件學(xué)報(bào),2011,22(增刊2):208-216.(ZHANG X Y, WANG Q, ZHANG Y Q. OpenBLAS: a high performance BLAS library on Loongson 3A CPU [J]. Journal of Software, 2011, 22(Suppl. 2): 208-216.)
[7] CHEN B, WANG L, WU Q, et al. Cross hardware-software boundary exploration for scalable and optimized deep learning platform design [J]. IEEE Embedded Systems Letters, 2018, 10(4): 107-110.
[8] LIN I, JEFF B, RICKARD I. ARM platform for performance and power efficiency — hardware and software perspectives [C]// Proceedings of the 2016 International Symposium on VLSI Design, Automation and Test. Piscataway, NJ: IIEEE, 2016: 1-5.
[9] VASWANI A, SHAZEER N, PARMAR N, et al. Attention is all you need [C]// Proceedings of the 31st Conference on Neural Information Processing Systems. North Miami Beach, FL: Curran Associates Inc., 2017: 5998-6008.
[10] WANG F, JIANG H, ZUO K, et al. Design and implementation of a highly efficient DGEMM for 64-bit ARMv8 multi-core processors [C]// Proceedings of the 44th International Conference on Parallel Processing. Piscataway, NJ: IEEE, 2015: 200-209.
[11] RUSITORU R. ARMv8 micro-architectural design space exploration for high performance computing using fractional factorial [C]// Proceedings of the 6th International Workshop on Performance Modeling, Benchmarking, and Simulation of High Performance Computing Systems. New York: ACM, 2015: Article No. 8.
[12] FLUR S, GRAY K E, PULTE C, et al. Modelling the ARMv8 architecture, operationally: concurrency and ISA [C]// Proceedings of the 43rd Annual ACM SIGPLAN Symposium on Principles of Programming Languages. New York: ACM, 2016: 608-621.
[13] LIU Z, JARVINEN K, LIU W, et al. Multiprecision multiplication on ARMv8 [C]// Proceedings of the IEEE 24th Symposium on Computer Arithmetic. Piscataway, NJ: IEEE, 2017: 10-17.
[14] XU X, CLARKE C T, JONES S R. High performance code compression architecture for the embedded ARM/ThUMB processor [C]// Proceedings of the 1st Conference on Computing Frontiers. New York: ACM, 2004: 451-456.
[15] 姜浩,杜琦,郭敏,等.面向ARMv8 64位多核處理器的QGEMM設(shè)計(jì)與實(shí)現(xiàn)[J].計(jì)算機(jī)學(xué)報(bào),2017,40(9):2018-2029.(JIANG H, DU Q, GUO M, et al. Design and implementation of QGEMM on ARMv8 64-bit multi-core processor [J]. Chinese Journal of Computers, 2017, 40(9): 2018-2029.)
This work is partially supported by the National Key R&D Program of China (2016YFB0201100, 2017YFB0202803), the National Natural Science Foundation of China (11871454, 91630204, 61531166003), the Strategic Priority Research Program of Chinese Academy of Sciences (B) (XDB22020102), the e-Science Foundation of Chinese Academy of Sciences (XXH13506-204).
GONG Mingqing, born in 1994, M. S. candidate. His research interests include high performance computation, machine learning.
YE Huang, born in 1979, Ph. D., associate research fellow. His research interests include high performance computation.
ZHANG Jian, born in 1972, Ph. D., research fellow. His research interests include high performance computation, scientific computation, visualization in scientific computing.
LU Xingjing, born in 1983, Ph. D. His research interests include high performance computation, deep learning, parallel programming, compiling technology.
CHEN Wei, born in 1984, Ph. D. His research interests include human-computer interaction, machine translation, deep learning.