深度學習在推斷階段的硬體實現方法概述

CopperDong發表於2018-04-09
眾所周知,深度學習(deep learning)在訓練階段完成模型的建立和引數調優,在推斷階段完成具體的實現及應用。這就好比造車的過程與開車的過程一樣,造車過程需要不斷嘗試“新設計-試車-調優”,而設計一旦定型後,就需要大規模生產製造,最終賣給使用者使用。設計車型(訓練階段)時候可以藉助各種工具和技術來加速研發與達到更高指標,但生產製造(推斷階段)時需要考慮成本、材料、市場等因素作出靈活適當的剪裁。深度學習在訓練階段常用GPU來加速訓練,在推斷階段可以用CPU、專用晶片(ASIC)、FPGA等實現。 GPU並行能力非常強大(內部包括上千核),但成本高昂、功耗大,不適合在無人機、航天、手機通訊等特定場景中應用; CPU作為通用晶片的代表,理論上將在訓練、推斷階段均可使用,但執行速度教慢導致不適合做訓練、功耗太大不適合在功耗有強烈要求的場景中做推斷; ASIC通常是針對某個演算法而設計的晶片,速度非常快,可以應用在推斷階段,但其設計週期長、成本高、缺乏靈活性不能適應深度學習演算法快速更新的要求;FPGA是一種通用的晶片,在速度和功耗上位於CPU和ASIC之間,可以針對硬體程式設計所帶來的並行行和靈活性可以很好地適應深度學習的需求(演算法更新+推斷階段的要求),但其開發設計難度較大,門檻高,需要掌握硬體電路除錯的知識。另外,像goolge的TPU、寒武紀的NPU,有人認為是一種ASIC,也有人稱其為專用處理器(並列與CPU、DSP之外的新型處理器),他們是針對深度學習領域的演算法(們)設計的一種計算晶片(顯然,這是在推斷階段),其內部設計了一套適合演算法(們)計算的通用結構,任何新的演算法只需對映(map)到特定到硬體結構上並按序執行即可,其好處是功耗、速度均得到了提升,不足是沒有配套的成熟的工具來支援其map過程。從應用者的角度來講,在推斷階段,CPU和FPGA是目前較好的選擇。從研究者的角度來講,尋找深度學習演算法的高效通用實現方法,並設計硬體架構和軟體編譯工具是當務之急。當然,硬體架構可以設計成專用處理、也可以用FPGA現有資源搭建,相應的軟體編譯工具也會有巨大差異。

    當前,深度學習在推斷階段的研究主要集中在以下幾個方面:降儲存、降計算、降功耗、提速度、 兼顧靈活性; 藉助的手段是量化資料、重用資料、優化計算結構、優化訪存技術等。其目的是,依據現有的硬體資源,尋找一個簡化的、易於實現的近似模型代替原先訓練好的模型,來做具體實現和應用,要求近似的精度(測試準確率)儘可能地高,即壓縮模型。為了達到模型精度上的逼近,許多方法中對新模型進行重新訓練,而訓練過程中會加入新的約束來保障後期易於實現。比如,BNN權重量化成1bit數時,需要重新訓練權重。(原先訓練好的模型是在32bit的浮點數上得到的高精度模型。)從更加巨集觀角度講,針對深度學習演算法的具體實現問題,可以建立一個模型來求解,該計算模型要執行速度快、計算量儘可能地小、資料儘可能地重用、儲存需求量儘可能地小,還能適應各種不同深度學習演算法等,假如設計出了該計算模型,軟硬體該如何分工與協同設計,硬體功能選擇專用處理器設計還是藉助FPGA資源來設計或是其他硬體計算平臺來設計,軟體功能該如何設計實現並與配硬體功能配合起來一起工作等。這就類似計算機採用圖靈計算模型、馮諾依曼體系架構實現一樣,用通用的計算模型和架構解決各種複雜的計算問題。顯然,要設計這樣的計算模型困難重重,但值得嘗試。 目前,採用這樣的思想典型代表有google TPU、寒武紀的NPU、深鑑科技的ESE、MIT的Eyeriss等。仔細分析他們的相似之處,可以發現:1)充分挖掘CNN卷積的內在並行能力,藉助移位暫存器和片上buffer實現快取和資料重用; 2)全部採用低精度的資料計算; 3)借鑑了CPU的設計理念,硬體分時複用+SIMD的處理辦法等。

    1)資料量化。減少資料的位寬不僅有助於降低儲存,還可以降低計算量,甚至簡化計算。在GPU上訓練時常常採用32位的浮點數; 而推斷階段受到片上儲存和頻寬的限制,需要減少位寬換取更大的快取來增加並行能力。 常用的量化精度有16bits,12bits,8bits,4bits,1bit, 有研究表明16bits與32bits在效果上非常接近(小於0.5%), 8bits的效果也在5%以內,因此,8bits非常受歡迎,許多廠商號稱支援8bits的深度學習應用。具體量化的方法,有簡單縮小位寬的,也有對數表示資料的,還有動態小數點將整數與小數分開的。不論那種都需要重新訓練才能確定權重資料。當然,32bits全精度的效果是參考標準。
     1bit的研究也是一個熱點,儘管看起來1bit的表達能力遠遠弱於32bits,但針對特定演算法的效果卻沒那麼糟糕。從BNN到BCNN、再到XNOR、到現在各種變體,不斷嘗試各種方法擴充其通用性和提高預測精度。BNN類的演算法非常適合在FPGA上實現,這是因為FPGA擁有大量的lut,可以精確地只針對位進行程式設計,而兩個1bit的資料乘法就是XNOR,權重可以實現儲存在lut中,然後給定輸入就可以立即得到結果,並不用大量的複雜操作,效率非常高。

    2)簡化網路結構。CNN相對全連線的神經網路是稀疏的,但相對計算資源來講還是複雜的。目前壓縮模型的做法主要包括:剪枝(pruning)、權重共享(shared weights)。剪枝就是將模型中某些連線去掉,減少計算量和儲存量,去掉的標準有權重接近0的、相對其他權重較小的等。權重共享就是將卷積核中所有元素(權重)劃成幾個類,同一個類中的元素都用“質心”來代替,這樣只需儲存幾個“質心”的值和每個元素歸屬哪個質心的索引即可,由於類別數都很少,索引所需的位寬用少量的幾位即可表示,從而起到壓縮模型的效果。也有人提出使用hash表來查詢權重,也是一種嘗試而已。

    3)資料重用。CNN影像卷積過程中會有大量資料重複使用,考慮到片記憶體儲空間有限,不可能將其全部讀入再去處理; 而按照輸出特徵圖形畫素點挨個計算的需求來讀取資料,則資料從外存到內部快取的頻寬瓶頸將會降低執行速度,而且每個資料重複讀取多次也是不可取的做法。顯然,資料重用必須在片上儲存空間、頻寬、計算資源三者之間尋找一個平衡點。MIT的Vivienne Sze等人仔細研究了可並行的三個維度:輸入影像區域性資料可在多個卷積核間重用; 卷積核可在輸入影像不同區域重用; 卷積核在不同輸入特徵間的重用(batch size>1),並在基礎上設計了一個CNN加速器(Eyeriss)。整張影像(可以是三維的)的卷積可以化為矩陣的乘法運算,因此,理論上講只要矩陣乘法優化做得足夠好,也可以達到加速的效果。為了達到資料重用的目的,研究人員設計了諸多結構,比如採用移位暫存器鏈+MAC(乘累加)實現卷積,也有采用PE單元+ 加法tree並行實現卷積等。資料重用的方式也會影響到讀取外存資料和寫出輸出特徵的方式。從巨集觀上講,計算模型決定了資料重用的方式、硬體架構設計、訪存方式、軟體編譯的設計等。

    4)計算結構。 現有幾乎每篇論文都會涉及計算架構,常用PE(process element)表示一個計算單元,具體功能不盡相同,但至少包括了卷積操作。除了PE之外,可能還會有區域性buffer,有的還會有一級快取負責從外部讀取資料再分發給二級快取進行區域性計算。當然,有些設計PE中包含了私有的buffer。 考慮到頻寬的影響,常常從外存讀取一塊資料進來,這時也會用到FIFO作為一級快取。PE單元內部的設計千差萬別,有的藉助移位暫存器鏈實現pipeline計算,也有先設計1-D的卷積單元、再組成2-D、3-D的卷積,還有搭建類似有ALU的結構。有些結構中甚至包括更大粒度的CU(Compute Unit)或PU(Process Unit)來執行更大粒度的並行。不論如何,整個設計中會包括若干PE、CU/PU以便並行加速計算。

    5)儲存結構。移位暫存器實現資料搬運是最簡單有效的方式,可以實現pipeline,也無需定址,控制器起來相對簡單。但是,在開始或資料重新載入時會出現若干週期無效資料,需要單獨剔除。而且,其比較適合一維順序情況。對於二維或三維的就需要同步,有些麻煩。FIFO也是一種常用的結構,可以設計成多維的,一個時鐘週期可以同時讓若干資料同時入隊或出隊。因此,FIFO可以滿足從片外快取大塊資料的需要(快取若干行輸入影像資料,快取若干行輸出特徵影像資料)。計算結構與儲存結構密切相關,正如人的左腿與右腿一般,缺一不可站立。
    6)編譯工具。計算模型解決了如何做的問題,硬體架構(計算結構+儲存結構)決定了硬體功能,編譯工具需要完成深度學習演算法向硬體架構的對映(map)的問題,讓其正確可靠地執行起來。編譯工具沒有一個統一標準,只能隨著硬體架構來設計。當前,caffe訓練好的模型結構儲存在prototxt檔案中,權重資料儲存在資料庫中。鑑於prototxt格式獨立與具體程式語言,且有很好地解析工具,諸多學者、廠商最先使用它作為深度學習模型的輸入格式,再向硬體結果對映。這裡存在軟硬體劃分的問題,如果硬體做的足夠多,軟體編譯器就會相對簡單點,但也會缺乏一些靈活性; 反之,軟體工作量會變大。這裡需要說明的一點是,這裡的編譯跟c/c++/python編譯到CPU不是一回事,跟FPGA開發中的綜合佈局佈線也不是一回事——因為目標硬體結構不同,對映過程差異也非常大。儘管許多人在FPGA上採用C/C++/Verilog/VHDL設計了深度學習加速器,並藉助vivado/quartus編譯生成了位流碼,但其本質只是將硬體架構在FPGA上實現了,即配置程式設計後的FPGA變成一個深度學習加速平臺,該加速器執行哪個深度學習演算法、怎麼執行,需要從prototxt編譯而來的“指令”才能知道。(這裡講的是通用加速平臺而非真的某個具體演算法編寫的verilog電路)。

     總之,當前主流的深度學習演算法在硬體上實現的主要集中在壓縮模型和設計計算模型兩個方面,前者著力尋找一個簡單有效易於實現的模型,後者重點在尋找一個基於現有硬體資源可以高效計算的方法,這二者的結合可以更加高效有效地解決推斷階段帶來的計算複雜和儲存爆炸等問題。

相關文章