卷積神經網路(cnn)主要由卷積層、池化層、全連線層和啟用層等網路層順序連線而成。本文主要針對計算密集型的卷積層,利用vivado hls工具對其在fpga上的實現進行加速。
乙個基本的卷積運算由6層for迴圈實現。如下面**所示,從外向裡的迴圈依次是k*k大小的卷積核,輸出特徵圖的行列(tr,tc),輸出通道數(tout),輸入通道數(tin)
kernel_row:
for(
int kr=
0;kr
}}}}
set_part
-tool vivado
create_clock -period 10
-name default
到此,我們總結一下vivado hls會做哪些工作:
1.將高階語言c/c++**轉換成等價的rtl**,並根據設定的時鐘週期和晶元延遲資訊,排程rtl的執行,並盡可能的將多個操作放在同乙個時鐘週期內執行;
2.根據directive語句進行特定的優化;
3.使用介面綜合語句指定資料傳輸所使用的匯流排協議。
下面,開始說卷積層加速的具體實現過程。主要涉及到以下幾方面
3.1 片上資源
vivado hls最終綜合形成的rtl**需要在fpga上執行。但fpg**上快取bram數量有限,而卷積層的參數量又是非常大的。一種解決方法是將大量的引數儲存在dram上,迴圈分片計算輸出特徵圖。下面是迴圈分片的**,我們對輸出特徵圖的行、列,輸入通道數,輸出通道數四個維度進行迴圈分片,從而保證fpg**上資源能夠滿足使用。
r_channel_tiling:
for(
int r=
0;r=tr)}}
}
3.2 平行計算fpga相比於通過處理器cpu來說,它有著優秀的並行處理能力。因此我們對卷積運算過程並行化,相比於其它維度,輸入通道和輸出通道更容易實現並行化。如下所示,利用一條pipeline語句即可實現。
kernel_row:
for(
int kr=
0;kr
}}}}
我們希望pipeline下面的**可以在乙個週期內執行完成,但目前還達不到這樣的效果。因為並行化後,乙個週期內需要對同一陣列進行多次讀寫,陣列預設的埠數是不能滿足該條件的。我們繼續對陣列進行優化。如下所示,在指定維度對陣列展開,從而提供多埠讀寫能力
data_t in[tin]
[s*tr+k-s]
[s*tc+k-s]
;#pragma hls array_partition variable=in complete dim=1
data_t w[tout]
[tin]
[k][k]
;#pragma hls array_partition variable=w complete dim=1
#pragma hls array_partition variable=w complete dim=2
static data_t out[tout]
[tr]
[tc]
;#pragma hls array_partition variable=out complete dim=1
到此,我們成功在fpga上實現了卷積層的平行計算過程。但還不能說在fpga上實現了卷積加速。計算能力有了,我們還缺少用來計算的資料。
3.3 資料傳輸
前面說過fpg**上快取資源有限,大量的引數是儲存在dram上的。fpga需要時,引數再通過匯流排從dram上傳輸到fpga上。這裡我們採用axi4匯流排協議傳輸資料,vivado hls中是利用inte***ce語句指定資料傳輸所使用的匯流排協議。
#pragma hls inte***ce m_axi depth=10800 port=in_addr bundle=bus0
#pragma hls inte***ce m_axi depth=55296 port=w_addr bundle=bus2
#pragma hls inte***ce m_axi depth=21632 port=out_addr bundle=bus3
平行計算需要大量的資料。可以利用datapack語句提高匯流排頻寬。
#pragma hls data_pack variable=in_addr
#pragma hls data_pack variable=w_addr
3.4 任務級並行資料讀取,卷積計算,寫回資料是在fpga上執行卷積運算的三個過程。上面三個函式能否在一定程度上並行執行呢?答案是可以的。vivado hls提供了dataflow語句實現任務級並行。至於任務級並行是什麼呢,可以參考這裡。我們實現時並沒有直接使用dataflow語句,而是用了(pingpong標記+if-else語句)實現的。綜合後的效果與dataflow語句基本等價。具體的實現過程可以參考原始碼,這裡就不列出了。
最後看一下綜合後結果
4.1 卷積引數和分片大小
4.2 綜合報告
4.3 資源使用
CUDA卷積加速 一
推出這個系列的目的呢,主要是因為cuda學習的乙個主要用途就是對影象處理進行加速,而處理影象的過程中經常要用到卷積。卷積的計算有多種形式,本系列主要研究的是二維矩陣的卷積計算。從最原始的計算方法 就是本科教科書上的那種 再到優化後的適用於大型資料的演算法,均提供並行化的設計思路。考慮到機器學習很火,...
More is Less 卷積網路加速
一篇講網路加速的 來自2017cvpr。目前做神經網路加速的主要有這幾個方面 低秩分解,定點運算 向量量化 稀疏表示 特殊的輕量級網路結構。再介紹本文方法之前,需要了解一下常見的卷積是怎樣實現的。以caffe中的卷積為例,首先通過im2col將輸入展開重排成乙個大矩陣,然後執行矩陣乘法。具體可參考知...
反卷積層(轉置卷積)
反卷積 deconvolution 不是數字訊號處理裡面的意義,在深度學習裡面應該叫做轉置卷積 transposed convolution 又名微步卷積 fractionally strided convolutions 也有叫backward strided convolution upconv...