周李敏,孫 靜,楊宏波,潘家華,王威廉+
(1.云南大學 信息學院,云南 昆明 650500;2.云南省阜外心血管病醫院 結構性心臟病病區,云南 昆明 650102)
心音信號在評估心血管疾病(cardiovascular disease,CVD)的初診篩查中起著至關重要的作用[1],但心音聽診在很大程度上取決于醫師的臨床經驗和檢查技能。與此同時人工智能興起,故而將深度學習應用于心音自動分類系統的研究應運而生[1,2]。心音自動分類系統包括心音信號預處理、特征提取以及分類3個部分,可將深度學習的方法用于分類部分以達到智能識別正、異常心音信號的目的。
卷積神經網絡(convolutional neutral network,CNN)和循環神經網絡(recurrent neural network,RNN)是深度學習的代表算法,但其計算密集、參數龐大的特點對擅長處理調度的中央處理器(central processing unit,CPU)并不友好[3]。圖形處理器(graphics processing unit,GPU)的架構雖適用于密集型計算,然而功耗太大的缺點導致其難以應用于移動端。專用集成電路(application specific integrated circuit,ASIC)具有低功耗、高性能的優點,但其研發周期長、成本高,難以做到廣泛的適配。現場可編程邏輯門陣列(field programmable gate array,FPGA)兼備GPU和ASIC的優勢,且可根據不同算法的運算邏輯靈活設計對應的硬件電路。故在FPGA上設計的CNN、RNN加速器將更適于實際的開發場景。
在硬件加速研究領域,Kowsaly提出了一種可替代傳統二叉樹加法器的新加法器,進一步降低了硬件利用率,從而顯著提升了CNN在FPGA上的運行效率[4]。張強使用高層次綜合(high-level synthesis,HLS)對CNN各層進行定制化編程,并利用流水線約束實現硬件加速,對比于單CPU部署方案效率提升了約14.7倍[5]。余運俊等采用剪枝的方法對長短期記憶神經網絡(long short-term memory,LSTM)進行精簡壓縮,并最終實現了低功耗下相對較高性能的LSTM加速器[6]。近年來,許多研究者將CNN和RNN應用于心音分類領域,取得了良好的分類效果[7,8]。LSTM神經網絡是一種特殊的RNN,在語音、自然語言處理等領域有不可替代的作用。Deng M等結合了CNN和LSTM兩種網絡架構,首次在心音信號分類過程中采用遞歸卷積神經網絡(recurrent convolutional neural network,CRNN),達到了目前效果最好的分類準確率[9]。雖然目前已有不少研究者設計了基于FPGA的定制化CNN或LSTM加速器,但缺少兼備CNN和LSTM優勢的CRNN硬件加速器。此外,定制化的加速器無法兼容不同網絡結構,且具有硬件占用率高、模型加載延時長的缺點。
為解決上述問題,本文設計了一個基于FPGA的CRNN硬件加速器,該加速器的CNN加速模塊可根據不同網絡結構進行動態配置,并將此加速器實際應用于心音分類系統中的分類部分。根據卷積層和LSTM層的運算特點,通過采用參數量化、交錯緩存、分片緩存、滑動窗機制及HLS指令優化等方法,在性能與功耗上取得了較好的加速效果。
CRNN的網絡結構非常靈活,其可由卷積層、LSTM層、池化層、全連接層4種通用部分組合構成。對于傳統卷積神經網絡而言,卷積層計算量占整個卷積神經網絡計算量的90%以上[10]。CRNN中除了卷積層以外,LSTM層中大量的向量矩陣乘法運算同樣需要消耗很大的算力。因此,CRNN硬件加速的核心在于卷積層和LSTM層。
卷積層由若干卷積核構成,目的是從輸入特征圖中提取更高級的特征。卷積核在輸入特征圖上滑動并與窗口內的像素點進行內積運算得到下一級特征圖。卷積核實際上是一種離散濾波器,濾波器參數即權值。卷積層運算的偽代碼如代碼1所示。
代碼1:卷積層前向計算偽代碼。
for(n=0;n for(h=0;h for(w=0;w { newsum=0; for(m=0;m for(j=0;j for(k=0;k sum+=Fin[h+j][w+k][m]*kernel[j][k][m][n]; Fout[h][w][n]=sum; } 從算法角度來講,一次完整的卷積層運算需要對N、H、W、M、K、J共6個維度進行循環遍歷(一般情況下J=K)。但實際上這6層循環之間互不依賴,調換順序也毫無影響,故可以根據加速器算力峰值、硬件利用率、邏輯復雜度、最終性能等參數來選擇如何展開循環以及展開到什么程度。通俗來講,就是選擇并行度類型以及并行度大小。常見的并行度類型如圖1所示[11]。 圖1 常見的卷積層并行度類型 (1)輸入通道并行,如圖1(a)所示。將代碼1中的輸入通道循環部分展開,同時計算PM個輸入通道的數據,因而并行度為PM。 (2)輸出通道并行,如圖1(b)所示。將代碼1中的輸出通道循環部分展開,同時計算PN個輸入通道的數據,因而并行度為PN。 (3)卷積核內并行,如圖1(c)所示。將代碼1中的卷積核行于列循環部分展開,同時計算PK個輸入通道的數據,因而并行度為PK。 LSTM神經網絡由Sepp Hochreiter等于1997年首次提出,它獨特的設計結構能夠存儲任意時間段內的長期依賴關系。LSTM由細胞狀態、輸入門、輸 入調制門、遺忘門以及輸出門5個部分組成,其中每個門包括一個向量矩陣乘法加權操作和一個使用激活函數的操作。細胞狀態的作用是讓LSTM能夠保持長期的記憶;門結構的作用是在每一時刻決定哪些信息應該保留,哪些信息需要遺忘。在信息傳遞過程中,LSTM通過門限機制對上一時刻細胞狀態、當前時刻輸入和上一時刻隱藏狀態進行處理從而達到刪除或者增加信息的目的。 圖2 LSTM層內部結構 如圖2所示,LSTM神經網絡的前向計算流程主要分為:忘記階段、選擇記憶階段、輸出階段[12]。忘記階段首先需要計算遺忘門的輸出ft,再根據計算結果對上一時刻輸入的細胞狀態ct-1進行選擇性忘記。該階段的計算公式為式(1) ft=sigmoid(Wfxxt+Wfhht-1+bf) (1) 選擇記憶階段首先需要通過計算輸入門的輸出it來對當前時刻輸入xt進行選擇性記憶,然后再計算輸入調制門的輸出gt,最后綜合考慮上一階段沒有忘記的信息以及本階段選擇記憶的新信息,完成當前時刻的細胞狀態ct的更新。該階段的算公式為式(2)~式(4) it=sigmoid(Wixxt+Wihht-1+bi) (2) gt=tanh(Wgxxt+Wghht-1+bg) (3) ct=ft⊙ct-1+it⊙gt (4) 輸出階段首先需要計算輸出門的輸出ot,然后再計算當前時刻細胞狀態ct經過tanh激活函數后的縮放輸出,最后綜合考慮決定當前時刻隱藏狀態ht。該階段的計算公式為式(5)、式(6) ot=sigmoid(Woxxt+Wohht-1+bo) (5) ht=ot⊙tanh(ct) (6) 傳統的FPGA開發是使用VHDL/Verilog硬件描述語言進行硬件電路設計的,該方法開發效率低、實現難度大。HLS可將C/C++直接綜合為VHDL或者Verilog,從而縮短了算法設計、驗證以及實現的開發周期。本文實驗將采用HLS開發方法對硬件電路進行模塊化設計,并對卷積層加速器和LSTM層加速器的設計與優化思路做重點介紹。 2.1.1 整體架構 網絡結構中不同的卷積層往往具有不同的類型參數,這些參數包括輸入輸出通道數、輸入輸出特征圖尺寸、卷積核個數及輸入通道數等。最簡單的硬件電路設計策略是針對每一層卷積層做定制化設計。但定制化設計的網絡模型在當前卷積層的計算完成后需要花費數百毫秒來重新配置新卷積層,嚴重影響了整體性能。為減少加載不同卷積層的延時,本文將設計具有高度兼容性的動態可配置卷積層,按照各個類型參數取其最大值的情況來設計一個適合所有卷積層的硬件架構。 本文設計的動態可配置卷積層加速器整體架構如圖3所示。直接存儲器訪問(direct memory access,DMA)通過HP接口訪問存儲在片外雙速率同步動態隨機存儲器(dual date rate synchronous dynamic random memory,DDR)中的數據,并將數據轉換成AXI4-Stream格式的流數據。先將當前卷積層的全部權值通過FPGA的AXI4-Stream總線從DDR傳入片上緩存Weight_Buffer,再將輸入特征圖通過AXI4-Stream總線從DDR傳入片上緩存Input_Buffer。鑒于模型參數龐大,Input_Buffer僅存儲本次計算需要的數據,待本次計算完成后再更新下一次計算需要的輸入特征值。數據處理模塊(data process module,DPM)從Input_Buffer中獲取輸入特征值、從Weight_Buffer中獲取權值,然后依次進行滑動窗乘法累加操作、輸入通道累加操作、激活函數操作,這里的激活函數選擇的是比ReLU效果更好的Leaky ReLU。計算完的輸出特征值先存入Output_Buffer中,待這一批的數據全部計算完成后,再通過AXI4-Stream總線將計算結果值從Output_Buffer傳回DDR以作為下一層卷積層的輸入特征值。Control通過AXI4-Lite接口控制卷積層加速模塊的啟動時序以及配置其具體參數。 圖3 卷積層加速模塊架構 2.1.2 定點量化 在FPGA上實現浮點運算的資源消耗和時間代價均比定點運算高[13],且CRNN模型的參數類型為32位浮點數,如果直接儲存將會占用較多FPGA內存資源,因此定點量化勢在必行。Int16定點量化能在保證計算精度的同時提高計算效率、減小內存耗用。按照式(7)、式(8)對輸入特征值、權值以及輸出特征值進行量化與反量化[14] (7) R=(Q-Z)×S (8) 其中,R表示浮點值,Q表示定點量化值,S表示所選定點量化模型中的最小刻度,Z表示所選定點量化模型中0的浮點值所對應的量化值。本文實驗中輸入特征值、權值、輸出特征值的數據位寬設為16 bit,其中高8位為整數位,低8位為小數位。為保留較高計算精度以及防止計算結果溢出,將中間計算值的數據位寬設為32 bit,其中高16位為整數位,低16位為小數位。 2.1.3 數據緩存 (1)Input_Buffer。以具有RGB這3個輸入通道的卷積層為例,輸入特征圖最簡單的緩存方法即順序傳輸各個輸入通道內的像素點至Input_Buffer,如圖4(a)所示。然而計算輸出特征值時,需要遍歷所有輸入通道對卷積結果進行累加,因此這種緩存方法會增加Output_Buffer的大小。解決方式是如圖4(b)所示的通道交錯式緩存,該緩存方法能夠明顯減少Output_Buffer的內存耗用。假設輸入特征圖尺寸為R×C,卷積核尺寸為K×K,CRNN模型中最大輸入通道數為M。為了同時對M個輸入通道執行交錯式緩存操作,故Input_Buffer應設計為M個尺寸為K×C的Line_Buffer。 圖4 順序緩存與交錯緩存對比 (2)Weight_Buffer。設CRNN模型中最大輸入通道數為M,最大輸出通道數為N,且卷積核尺寸為K×K。考慮到最糟糕的消耗情況,Weight_Buffer應設計為M×N個尺寸為K×K的緩存區。 (3)Output_Buffer。設CRNN模型中最大輸出通道數為N,Output_Buffer用于緩存當前卷積層輸出特征圖所有輸出通道上同一位置的像素點,故Output_Buffer設計為1×N的緩存區。 2.1.4 核心運算設計 DPM是卷積層加速器的運算核心,而滑動窗乘法累加單元又是DMP的核心單元,接下來著重介紹一下該單元的運算機制與并行優化設計。 (1)滑動窗機制。圖5(a)為輸入特征圖。如圖5(b)所示,Line_Buffer本質是一個移位寄存器陣列,每當捕獲到新的輸入特征值時,對應列的數據將會向上移位,并在該列插入新的輸入特征值。以此類推,直至緩存到輸入特征圖的最后三行。如圖5(c)所示,當輸入特征圖的前兩行和前三列緩存完成后,才會觸發第一次卷積運算。第二次觸發卷積運算如圖5(d)所示,之后每更新3個新數據,觸發一次卷積運算。滑動窗口負責從Line_Buffer中拾取數據并觸發卷積,設卷積核尺寸為K×K,則滑動窗口也應設計為窗口大小為K×K的Window_Buffer。 圖5 滑動窗機制 (2)HLS指令優化。本文實驗主要使用了HLS中的PIPELINE指令和ARRAY_PARTITION指令對算法進行優化。循環內層對數據的操作大致可分為3個步驟:讀取數據、計算數據、存儲數據。PIPELINE指令是HLS中增加硬件運算并行度的一項重要的優化技術,其能將循環外層完全流水,最大程度地增加并行度從而提升系統的吞吐量。ARRAY_PARTITION指令可以將多維數組分割成多個獨立的模塊,從而可以在同一個時鐘周期內讀出多個數據,提高數據帶寬。假設權值數組的尺寸為N×M×K×K,并用ARRAY_PARTITION指令將其重新排列成(Cout,Cin,K×K)的3D陣列。定點量化后權值的數據位寬為16位,故64位的DMA傳輸模式最多可以并行4個輸入通道,也即Cin=4,相應地,Cout=(N×M)/4。 (3)并行計算設計。由圖1知,常見的并行度類型有:輸入通道并行、輸出通道并行、卷積核內并行。上文分析到由于數據位寬和DMA傳輸模式的限制,最多只能并行4個輸入通道,故只需要4個Window_Buffer配合Line_Buffer完成滑動窗乘法累加計算。相應地,輸入通道并行度PM=4。當Line_Buffer緩存至輸入特征圖第K行及第K-1列數據后,觸發Window_Buffer內第一次卷積計算。滑動窗乘法累加運算相當于對卷積核內行列循環進行展開,同時計算K×K個數據,因此卷積核內并行度PK=K×K。理論上不同卷積核之間的卷積計算相互獨立,因此在硬件資源充足的條件下,輸出通道并行度PN=N。對卷積層運算進行并行化設計后的偽代碼如代碼2所示。 代碼2:并行優化后的卷積層偽代碼。 weight_typeweight[M][N] #pragmaHLSARRAY_PARTITIONvariable=weightblockfactor=4dim=1 for(i=0;i for(j=0;j for(k=0;k { #pragmaHLSPIPELINEI1=1 load_weight; } for(r=0;r for(c=0;c for(m=0;m { #pragmaHLSPIPELINEI1=ICONV line_buffer; sliding_window; conv_mac; output_stream_merge; } 2.2.1 整體架構 CRNN模型通常僅有一層LSTM,故為提高硬件電路設計效率,本文將對LSTM層執行定制化設計方案。定制化設計的LSTM層加速器整體架構如圖6所示,主要包括緩存區、向量矩陣運算區、逐點運算區。為方便分片緩存及后續運算,首先將當前時刻輸入xt和上一時刻隱藏狀態ht-1合并為一個長向量Input_Vec,同時將輸入門、輸入調制門、遺忘門以及輸出門各自的權重合并為一個大的權重矩陣Weight_Mat,然后對Input_Vec和Weight_Mat執行向量矩陣運算,并將其計算結果傳輸到Adder_Tree組件進行并行累加,最后加上偏置向量Bias_Vec得到向量矩陣運算區最終運算結果。在逐點運算區,根據式(1)~式(6)計算分別得到it、gt、ft、ot、ct、ht,并將當前時刻細胞狀態ct、當前時刻隱藏狀態ht傳輸至緩存區用于下一時刻各項數據的計算。 圖6 LSTM層加速模塊架構 2.2.2 分片緩存 LSTM層參數主要包括權重矩陣Weight_Mat和輸入長向量Input_Vec,其中Weight_Mat包含了Wix、Wgx、Wfx、Wox、Wih、Wgh、Wfh、Woh。由于FPGA存儲資源和查找表數量有限,本文將對權重矩陣和輸入長向量采取分片緩存策略。如圖7所示,Input_Vec的大小為(Input_Vec+Hidden_Size),合并后的Weight_Mat的大小為(Input_Vec+Hidden_Size)×(4×Hidden_Size)。Input_Vec和Weight_Mat均被劃分為長度為32的片區,不足32的部分填充0補齊。在向量矩陣運算過程中,將Input_Vec的每一個分片都與Weight_Mat的對應數據相乘累加,直至遍歷完Input_Vec的全部分片。片緩存區中數據的乘法累加操作仍通過滑動窗完成,滑動窗口大小為1×32。向量矩陣運算部分的偽代碼如代碼3所示,同樣使用了HLS指令中的PIPELINE與ARRAY_PARTITION指令對算法進行并行優化。 代碼3:LSTM層向量矩陣運算偽代碼。 weight_typeweight[4*Hidden_Size][(Hidden_Size+Input_Vec)/32]; #pragmaHLSARRAY_PARTITIONvariable=weightblockfactor=4dim=1 for(i=0;i<4*Hidden_Size;i=i+1) for(j=0;j for(k=0;k<32;k=k+1) { #pragmaHLSPIPELINEI1=1 load_weight; } for(i=0;i<4*Hidden_Size;i=i+1) for(j=0;j for(m=0;m<(Hidden_Size+Input_Vec)/4*32;m=m+1) { #pragmaHLSPIPELINEI1=ILSTM tile_buffer; sliding_window; tile_mac; output_stream_merge; } 圖7 分片緩存 2.2.3 激活函數 FPGA實現激活函數的常用方法有泰勒級數展開法、查找表法以及分段函數擬合法等。泰勒級數展開法擬合效果最佳,但復雜的運算會消耗大量乘法器資源,且計算時間較長。查找表法最為簡單快速且不消耗乘法器,但其需要事先將不同變量對應的函數值存入ROM中。隨著函數計算精度的提高,其所需的存儲資源會顯著增加。本文采用的分段函數擬合法將低階多項式和查找表相結合,很好地平衡了計算精度與計算時間之間的矛盾。 sigmoid函數和tanh函數的表達式如下[15] (9) (10) 利用MATLAB內置函數polyfit分別擬合式(9)、式(10)得到sigmoid、tanh的擬合函數。因LSTM層的輸入輸出數據均量化為16位定點數,故需對擬合函數進行相應倍數放大。修正后的sigmoid、tanh擬合函數見表1、表2。如若輸入數據為負數,則將其轉換為補碼再根據式(11)求解。運算過程中除法涉及的除數4096為2的冪次方,因而可以通過移位寄存器輕易實現 f(x)=4096-f(65 536-x)(32 768≤x≤65 535) (11) 表2 FPGA擬合tanh函數 本文設計的遞歸卷積神經網絡加速器選擇ARM+FPGA異構SoC硬件平臺進行開發,其中FPGA作為從處理器部署CRNN加速器,ARM作為主處理器通過AXI4-Lite接口與CRNN加速器交互并控制其運行。實驗平臺為Xilinx公司Zynq-7000系列的ZedBoard開發板,開發環境為Vivado HLS 2019.01。PC端操作系統為Windows 10,其中央處理器型號為Intel Core i7-9750H CPU 2.60 GHz,其顯示適配器型號為NVIDIA GetForce GTX 1660 Ti。 本文實驗中所使用的心音數據來自于心音挑戰賽數據庫,研究者可從PhysioNet網站上自行下載。先對心音信號進行小波去噪,然后采用梅爾對數頻率系數(log Mel-frequency spectral coefficients,MFSC)對其進行特征提取,最后將輸出的32×16時頻特征圖輸入到不同模型中進行分類[16]。其中包含66 688張訓練圖、11 724張測試圖。圖8為不同模型中心音分類算法的性能對比。實驗結果表明CRNN-a模型對心音信號的分類效果最佳。如表3所示,模型CRNN-a除輸入層外共分為5層,分別是卷積層C1/C2、LSTM層LS3、池化層S4、全連接層F5。在PC端完成CRNN-a模型的訓練過程后,保存訓練參數值并對其進行Int16定點量化,最后再移植到FPGA硬件平臺中。 圖8 不同模型中心音分類算法性能對比 表3 CRNN-a的網絡結構 在100 MHz的時鐘頻率下,PL端的各模塊資源占用情況見表4,資源利用率見表5。卷積層中的卷積運算和LSTM層中的向量矩陣運算均需要使用大量乘法器,且LSTM層中的激活函數運算還需要用到查找表,故DSP和LUT的利用率都很高。此外,卷積層和LSTM層均有規模龐大的權值矩陣和偏置向量需要緩存到BRAM中,故BRAM的利用率也很高。FF主要用于構成移位寄存器。綜上所述,各項資源的利用率都很高,表明此硬件加速器架構合理。 表4 各模塊資源占用 該硬件加速器與CPU、GPU的對比結果見表6。可以看出,FPGA僅需0.569 ms便可完成對一張心音特征圖的識別分類工作,其識別速度是CPU的29.79倍,然而CPU 表5 資源消耗 表6 CRNN硬件加速器與CPU對比 的功耗卻是FPGA的5.89倍;該加速器雖然在識別效率方面稍遜GPU平臺,但性能功耗比約為GPU的20.2倍。綜上所述,基于FPGA的CRNN加速器相比于CPU和GPU,在性能和能耗方面有巨大優勢,具有相當的實際應用價值。 本文以實現CRNN加速器為目標,采用模塊化設計的方法著重對計算量龐大的卷積層和LSTM層提出了加速方案。為了有效地實現卷積運算利用了輸入通道交錯緩存操作和滑動窗計算機制,針對LSTM層的向量矩陣運算提出了分片緩存以達到分片復用、并行計算的目的,并使用PIPELINE指令將循環外層完全流水最大程度地增加并行度以及提升吞吐量,使用ARRAY_PARTITION指令對多維數據進行再分割以提高數據帶寬。在Xilinx平臺上的驗證實驗結果表明,與CPU和GPU相比,該CRNN加速器在性能和功耗兼顧的情況下取得了29.79倍加速效果,以及20.2倍的高能效比優勢。 接下來的研究應從以下兩個方面優化: (1)通過剪枝對權重矩陣和偏置向量做稀疏化處理,以減少DSP和BRAM資源消耗,并將剪枝后的CRNN模型映射到FPGA上。 (2)將LSTM層加速模塊設計為具有高度兼容性的動態可配置架構。
1.2 LSTM層運算理論

2 加速實現方案
2.1 卷積層加速器設計



2.2 LSTM層加速模塊設計




3 實驗及結果分析
3.1 實驗環境
3.2 測試數據集與網絡模型


3.3 結果分析



4 結束語