一. 基本性能指標
for循環優化的基本概念、對for循環施行流水的優化、for循環的展開以及for循環的循環變量的數據類型是否對結果資源有影響
1. 流水線優化
2. for循環的展開
- 默認情況下for循環是被摺疊的,所謂摺疊可以理解爲所有每次循環都是採用同一套電路,只是這個電路被分時複用,而展開就意味着這個for循環被複制了n或者n/2份,這個是可以設置的;
- for循環可以部分展開,比如trip count爲6時,可以將for循環拆分成3個,分別對應(0,3)、(1,4)、(2,5)次循環,其中同組的共用一套邏輯資源;
3. 循環變量i
正常情況下,循環變量i的類型不會影響最後的綜合結果,因爲Vivado HLS考慮的是i的最大值,然後使用FPGA的最小資源
4. 總結
二. for循環優化——循環合併
- 兩個相互獨立的for循環我們期望可以並行執行,但是在默認情況下,HLS是順序執行的,我們可以在HLS中通過directive來將兩個for循環合併;
- 合並可以幫助我們在一定程度上降低latency,這是因爲在默認情況下for循環都會創建額外的狀態機,而狀態機會佔用額外的時鐘週期和資源;
- 當循環邊界不一致時,以較大的那個作爲合併後的循環邊界;
- 如果一個循環變量是邊界,而另一個是變量,這個時候不能合併,會報錯;
- 如果兩個循環邊界都是變量,同樣合併時會報錯;
對於變量作爲邊界的for循環如何合併?
合併的規則:
- 循環邊界都是常數且不一致時,合併後的循環邊界由較大的邊界決定;
- 邊界都是變量時,要求兩個變量能夠達到的最大值是一致的,這保證了它們有相同的迭代週期;
總結:
三. for循環的優化——數據流
循環之間有依賴關係,可以應用流水線,不可以用合併;
沒有應用數據流時循環執行順序爲左,應用了之後爲右,可以看出來,使用了數據流之後我們並不需要前面的循環完全執行結束後才執行下一個循環任務,只有前面的有輸出我就可以做下一個子任務了。同時各個任務之間有交疊,這幫助我們降低latency進而提高數據吞吐率。
dataflow優化的限制:
- single-producer-consumer Model,兩個循環同時使用前面的同一個變量,不能應用數據流,改善的方法是在前面將這個變量分別賦給不同的兩個變量,進而這兩個變量分別進入不同的循環;
- Bypassing Tasks Model,temp3的數據來自loop2,所以不能使用合併和dataflow,改善的方法是在中間循環中通過簡單的複製消除bypass;
- Configuring Dataflow Memory Channels,HLS實現不同任務之間的channels是通過ping-pong或者FIFO緩衝器;如果參數類型爲scalar、pointer、reference,HLS會將其綜合成FIFO,如果是個數組,HLS判斷出數據流是順序的就會配置成FIFO,否則就是ping-pong RAM;
- 也可以使用cofig_dataflow configuration顯式地告訴HLS要配置成FIFO還是ping-pong RAM,配置成FIFO時要特別注意FIFO的深度,否則在C和RTL協同仿真時會報錯;
總結:
四. for循環優化——嵌套的for循環
三種類型的嵌套for循環:
- Perfect loop nest:循環的邊界都是常量,同時循環體只會在最內層的for循環中出現;
- Semi-Perfect loop nest:最外層循環的邊界是變量,但是最內層for循環邊界是常數,同時循環體一定在最內層for循環;
- Imperfect loop nest有兩種,一種是循環邊界都是常量,但是外部循環也有循環體,第二種是雖然外部循環沒有循環體,但是內部循環的邊界是變量;
對於Imperfect loop,我們希望通過一些手段將其轉化成Perfect或者Semi-Perfect loop。
對某層for循環做流水,該層下面的for循環都會被展開;
不加任何約束、對最內部做流水、中間層做流水、最外部做流水的比較:顯然對最外部做流水的延遲最小,但對應的增加了硬件成本;同時對整個函數做流水會將所有層都展開,延遲最低,硬件成本最高。
矩陣乘法優化:
總結:
五. for循環優化的其他方法
1. 並行化的問題
2. Loop Pipeline with Rewind Option
rewind並不是適合所有for循環,它是有條件的。
什麼時候使用Pipeline會失效?
當將一個任務做流水時,for循環下面的操作都會被展開,如果for循環邊界是變量時,這個操作就會失敗;
3. 如何處理循環邊界是變量的情形?
當循環邊界是變量時,HLS無法確定loop的latency,進而無法確定整個函數的latency。
對於這種情形有三種解決方法:
- 使用Tripcont這種directive,這種方法不會對綜合結果有任何影響,只是用於report的顯示以及不同solution之間的比較;
- 將循環邊界的數據類型聲明爲 ap_int,對綜合結果有優化;
- 在C代碼中使用assert macro;
三種方法的比較:可以看出來,使用assert的方式latency最小,硬件成本也最低。
總結: