闞保強
(福建師范大學 協和學院 信息技術系,福州 350003)
隨著計算技術的發展,數字圖像處理技術的使用越來越普遍,在醫學工程、計算機工程、宇航制導、航空航天等研究領域都有大量數字圖像處理技術的使用[1].在數字圖像處理中,要進行圖像的匯聚、模糊處理、邊緣增強和邊緣檢測等典型算法中都要使用卷積作為核心運算單元.隨著近年來深度學習技術在圖像識別領域的極大成功,卷積神經網絡(CNN)受到越來越多的關注.而要提高CNN 的計算性能,就需要高效的卷積實現.基于現場可編程門陣列(FPGA)實現高速圖像處理系統一直是一個非常活躍的研究領域,這主要得益于FPGA 的位級并行計算能力、像素級處理以及鄰域級與任務級的處理能力,可使得計算和速度達到更好的性能.另外,FPGA是可重配置的,從而能夠更好的滿足神經網絡的靈活性需求.正是FPGA 這種兼具靈活性與并行處理的能力,使其成為開發神經網絡硬件加速計算領域的首選平臺[2].
針對圖像卷積實現的問題,有不少學者進行了研究,大部分工作集中在高性能、低資源以及FPGA 面積使用效率上.正如文獻[3]所指出的,塊隨機存取存儲器(BRAM)是經常使用的一種解決方案,但這種方案是以較高的能耗為代價的.為了降低能耗,在結構設計上,可以通過圖像部分性存儲或完全存儲來減少BRAM的使用.對于完全性圖像存儲,主要通過應用并行化提高處理能力,并通過資源重用降低復雜性.對于部分存儲架構,則是將圖像分割成與使用的卷積器一樣多.這些方案的缺點是模塊化設計不夠,使得難以簡單通過增加并行度來提高工作效率[4–6].
為此,本文提出了一種基于動態重用BRAM 的圖像卷積模塊化實現架構,并給出了并行結構實現中的復雜度.實驗表明,當并行度提高時,BRAM 的復雜度只是線性增加,這無疑會極大降低系統功耗和復雜度.
本文安排如下:第2 部分簡要介紹圖像卷積算法及設計流程.第3 部分介紹了模塊化設計架構及各模塊的組成.在第4 部分,給出了硬件實現和實驗結果.最后,給出本文結論.
得益于卷積固有的局部提取和二維特性,在圖像處理算法中,圖像卷積運算是經常使用的.由文獻[3]知,圖像卷積的定義為:

其中,I(x,y)是大小為(m×n)的圖像在(x,y)處的像素值,w(i,j)大小為(k×k)的卷積核,由一組系數構成,而I′(x,y)為有效卷積結果,大小為(m–2)×(n–2).
由于圖像卷積算法的并行性非常適于FPGA 實現,從而提高計算性能,所以本文將重點研究如何更有效進行二維卷積設計,以減少FPGA 資源的使用.
為了便于硬件實現,這里主要采用圖像的灰度值.考慮到每個通道可以視為獨立的灰度圖像,所以本文方法易于推廣到具有多個通道的圖像上.
對于圖像像素I(x,y)的灰度值動態范圍一般在[0,255],卷積核w(x,y)可以為負或正.這里把像素灰度值做歸一化處理,也就是轉換像素值為T[I(x,y)] =IT(x,y),其范圍為[0,1].對于卷積核系數經極大范數化轉換為M[w(x,y)]=w′(x,y),其范圍限制為[?1,1].因此,可以將上述公式變換為:

其中,T?1(.)表示歸一化處理的逆變換,其范圍為[0,255].圖1給出了整個數據映射過程,先對輸入圖像進行歸一化,然后將其與內核進行卷積,最后將計算結果進行逆變換以重新映射到標準灰度值.

圖1 圖像處理映射關系圖
對于硬件運算,有浮點表示和定點表示[3].浮點表示以尾數和指數形式存儲數字,支持浮點格式的硬件在每次執行計算后會自動縮減尾數并更新指數,以使結果與設定的位數相對應,這些操作使支持浮點的硬件在面積和功耗方面犧牲較多.一種替代方法就是定點表示.定點表示主要存儲和處理具有固定位的數據.這意味著在計算之后,不遵循小數點的位置,小數點,無論是否冗余,對于每個變量都是固定的,并且是預定義的.這種設置在資源利用方面具有優勢,但如果計算結果超出范圍,發生溢出,需要根據系統選擇適當的表示形式.
為了以最小位數表示用于圖像像素和內核值,需要研究具有可接受的信息損失下的最小分辨率位數.如前所述,像素的值在0 到255 的范圍內,通過歸一化,限定為0 到1 的范圍.卷積核既可以是正數,也可以是負數,使用極大范數化使卷積核限制在?1 到1 的范圍.為了以8 位表示上述值范圍,這里采用有符號定點表示S(8,7).假定圖像以K3×3進行卷積會產生20 位輸出,對于每個乘積結果乘以S(16,14),9 個元素的總和為S(20,14),經過處理后,將結果取正并截斷,去掉小數部分,用S(13,8)表示.
為了便于系統化和模塊設計,采取系統級軟硬件協同設計方法,整個設計流程圖如圖2所示.首先,基于設計規范,進行軟硬件劃分;在軟件開發部分,先通過上位機(采用Python 語言)進行浮點計算的模擬,然后,在軟件層面分析定點運算實現系統的結果,驗證所描述的硬件模擬器產生的位是否與浮點運算模擬器的位相匹配,然后在FPGA 中進行硬件設計.在FPGA 硬件設計中,通過軟硬件協同驗證,再次檢查硬件驗證的結果與模擬結果是否相同,不同的話再進行定點位數的調整,直到滿足設計要求,最后完成設計.
將整個設計流程分成以下幾個階段:
(1)預處理階段:通過上位機使用Python 腳本利用第2 節中提到的轉換來獲取圖像.上位機腳本程序可將映射圖分成幾批進行處理,然后分批通過端口(UART)將其發送到下位機FPGA.單個批次的連續像素大小由使用的MAC 單元數量決定.
(2)處理階段:將批處理圖像與卷積核進行卷積操作.所述卷積核是可配置的,用戶可以通過GPIO 加載相同的系數.卷積操作完成后,數據發送到FPGA 中的微處理器,并給出恢復批處理的順序,以便將其返回到上位機.
(3)后處理階段:在后處理中,上位機使用Python腳本組合上傳來的一個或多個批次圖像像素,并通過逆變換恢復為標準灰度值.
整個系統設計分成8 個處理過程,如圖3所示.啟動后,系統必須初始化,通過接收初始化信號以使自身進入該狀態,等待配置.接收到相應的指令后,系統將進入卷積核系數裝載狀態,即將卷積核系數加載到系統中.緊接著進行待分批處理像素大小設置,即圖像的大小,這決定了最后一個數據在內存中的位置.狀態的轉換通過指令碼的方式進行控制,未收到指令碼時,系統保持狀態不變.批次存儲后,將進入卷積運算狀態,在此狀態下完成批次卷積處理.一個批次的圖像處理完成后,將發出通知,并將批處理完的結果返回到上位機.

圖2 系統設計架構圖

圖3 系統處理流程圖
為了實現內存的動態復用,即在每次批處理中重復使用內存加載的數據,整個卷積實現系統采用圖4所示的模塊化設計.主要包括接口控制單元:負責卷積處理模塊與嵌入式內核MCU 之間的通信;地址管理器(AMU):用于生成待讀取或寫入數據的存儲地址;數據存儲管理單元(DMU):用于管理待寫入或讀取數據的存儲空間;乘累加器(MAC)單元:執行卷積核系數和圖像像素之間乘積累加和操作;存儲單元,由FPGA的BRAM 組成的一組存儲單元,大小取決于實例化的MAC 數量,即系統所需的卷積并行處理要求.
接下來,具體闡述各個功能模塊的具體實現方法.
2.3.1 存儲單元
為了批量存儲,采用BRAM 列排的形式,每一列對應于一個批次中的一欄.批處理的大小由圖像的高度和實例化內存數確定.因此,圖像的最大高度(以像素為單位)必須小于或等于實例化內存的地址數.在批處理期間,每個像素只能讀取一次,從而可以更有效地使用內存.已讀取的批處理像素將被處理后的像素覆蓋,這樣可以減少所需的內存量.對于存儲單元有兩個數據端口,一個用于輸入數據,一個用于輸出數據,還有一個讀寫控制信號.

圖4 卷積部分實現結構
2.3.2 接口控制單元
接口控制單元模塊負責模塊與FPGA 中的處理器之間的接口.為此,它具有兩個32 位端口,分別連接到處理器的內部和外部的GPIO.該單元主要通過接收指令完成以下控制功能:加載卷積核,用于加載卷積核系數,每個系數設為8 位;配置圖像尺寸,必須與圖像的高度(以像素為單位)一起使用,使用10 位,因此最大尺寸為1024 px;圖像批處理加載,一個批次的像素加載;批處理完成,表示正在加載的像素是批處理中的最后一個像素,一旦收到此指令,模塊將進入運行狀態,在該狀態下執行處理;恢復數據,要求模塊提供下一個已處理的像素.
2.3.3 地址管理單元(AMU)
AMU 負責生成DMU 占用的內存地址.在圖像加載狀態期間,AGU 負責生成寫入此數據的地址,為此,它具有一個計數器,該計數器隨控制單元輸入遞增.AMU 通過比較圖像的高度,向DMU 發送指示信號,表明接下來接收到的像素屬于批次的新列.在運行階段,AMU 必須產生兩個不同的地址,一個指向DMU傳送到MAC 單元的數據地址,另一個指向DMU 存儲MAC 處理后數據的地址.兩個地址每個時鐘周期增加一次,因為MAC 生成每個周期處理的數據.讀地址和寫地址之間的差等于從將第一個像素傳送到MAC單元到準備好存儲第一個已處理像素為止的等待時間.
2.3.4 乘法累加器單元(MAC)
MAC是并行實例化的單元,它們負責進行乘加計算以執行卷積.對于卷積核(3 ×3)的卷積運算需要9 條記錄存儲系數以及9 條記錄存儲當前正在處理的批次像素值.MAC 具有單個數據輸入端口,其中輸入了3 個系數(對應于一行)的卷積核或批處理部分(如來自控制單元的信號所示),此外還有另一個控制信號,用于指示應修改記錄還是保持.
對于大小為(k×k)的內核,加載每列的k個像素,在其中保留(k×k)個像素,然后,將像素乘以核系數,將每個項相加.對于最終求和結果,送出前,會做截斷處理.處理完像素后,將存儲批次像素的記錄進行移位,即新的一行,它等效于FIFO 結構.該操作的硬件實現如圖5所示.

圖5 基于MAC 的卷積硬件實現結構圖
2.3.5 數據存儲管理單元(DMU)
為了有效利用存儲器,必須考慮并行度.DMU 的作用就在于建立存儲器和其余單元之間的接口,從而獨立于并行處理需求而降低其復雜性.對于k×k的卷積核,需要使用k列作為輸入以在MAC 中生成處理后的列.因此,對于兩個MAC 需要2k列.對于卷積運算,要得到連續的列,必須將輸入列移位一次.那么對于MAC 輸入的相鄰列就有可能存在重復,所以可通過共享來降低開銷.
這樣的好處是,與每個MAC 單元都使用獨立的存儲器列相比,在不同的MAC 之間共享信息可以極大節省所需的BRAM,而循環移位可以節省傳輸的信息量.
為了實現以上功能,該模塊在內部由兩部分組成:一個數據多路復用器模塊,用于傳遞存儲器和MAC 的信息;一個基于有限狀態機(FSM)的控制部分,用于處理存儲器的控制信號(寫使能)和數據多路復用器的控制信號.
為了在FPGA 中實現該設計,本文選擇使用了Vivado 環境.預處理(浮點模擬和圖像歸一化)和后處理(圖像標準灰度值轉換)均在上位機實現.卷積核系數和相應的圖像批處理都通過串口加載到FPGA上.在FPGA 的運算使用定點表示,對輸入和輸出圖像(處理后的圖像)的分辨率設定為8 位.綜合后的系統級模塊圖如圖6所示.
通過上位機利用Python 腳本構建不同的卷積核,使用的卷積核包括:[0,0,0;0,1,0;0,0,0],[0,?1,0;?1,5,?1;0,?1,0]和[?2,?1,0;?1,0,1;0,1,2],并在上位機對圖像進行卷積處理.然后,采用相同的卷積核使用FPGA 對圖像進行卷積處理.圖7給出了上位機模擬結果和FPGA 實現結果的比較.

圖6 系統功能單元圖

圖7 上位機模擬效果與FPGA 實現效果比較圖
該設計針對不同程度的并行性需求進行了綜合.圖8(a)分別給出了2 個實例并行化至24 個實例并行化的資源使用情況,根據系統中的并行度,可以看到復雜度呈線性增加.圖8(b)、圖8(c)分別給出了8 個實例并行化和24 個實例并行化的資源使用詳細分布.圖9給出了存儲開銷使用情況,傳統的圖像卷積實現,BRAM 基本是隨著卷積單元數以1:1的比例增長,本文的方法可以使得存儲開銷顯著的下降.

圖8 資源占有情況分析

圖9 資源占有情況分析
本文主要研究了如何在FPGA 中模塊化實現圖像卷積運算.在具體實現上,主要采用了圖像按列批次處理,分批加載到FPGA 上,然后進行卷積運算,在設計中利用臨近批次數據重復性這一特征,運用內存共享機制,有效降低了BRAM 的使用,實驗表明并行度的提高僅線性增加BRAM;整個系統設計基于裝載、處理、輸出的流程機制,可實現(k×k)卷積核的重配置,具有較好的擴展性.