4.2.3. 例 : ループのパイプライン処理および展開
1. #define ROWS 4
2. #define COLS 4
3.
4. component void dut(...) {
5. float a_matrix[COLS][ROWS]; // store in column-major format
6. float r_matrix[ROWS][COLS]; // store in row-major format
7.
8. // setup...
9.
10. for (int i = 0; i < COLS; i++) {
11. for (int j = i + 1; j < COLS; j++) {
12.
13. float dotProduct = 0;
14. for (int mRow = 0; mRow < ROWS; mRow++) {
15. dotProduct += a_matrix[i][mRow] * a_matrix[j][mRow];
16. }
17. r_matrix[i][j] = dotProduct;
18. }
19. }
20.
21. // continue...
22.
23. }
このコンポーネントのパフォーマンスを向上させるには、特定のカラムの各エントリーで繰り返されるループを展開します。ループ動作が独立している場合、コンパイラーでは、それを並列実行します。
浮動小数点演算を実行する順序は、通常、ソースコードで表現されているのと同じにして、数値精度を維持してください。ただし、--ffp-contract=fast コンパイラー・フラグを使用して、浮動小数点演算の順序を緩和することができます。浮動小数点演算の順序を緩和すると、このループ内のすべての乗算が並行して発生する場合があります。詳細については、次のチュートリアルを確認してください。 <quartus_installdir>/hls/examples/ tutorials/best_practices/ floating_point_ops
コンパイラーでは、展開することでパフォーマンスが向上すると考えられる場合、ループを単独で展開しようとします。例えば、14行目のループは自動展開されます。これは、ループのイタレーション回数は一定であり、多くのハードウェアを消費しないためです。(ROWS は、コンパイル時に定義された定数です。これにより、このループのイタレーション回数が一定になります。)
01: #define ROWS 4
02: #define COLS 4
03:
04: component void dut(...) {
05: float a_matrix[COLS][ROWS]; // store in column-major format
06: float r_matrix[ROWS][COLS]; // store in row-major format
07:
08: // setup...
09:
10: for (int i = 0; i < COLS; i++) {
11:
12: #pragma unroll
13: for (int j = 0; j < COLS; j++) {
14: float dotProduct = 0;
15:
16: #pragma unroll
17: for (int mRow = 0; mRow < ROWS; mRow++) {
18: dotProduct += a_matrix[i][mRow] * a_matrix[j][mRow];
19: }
20:
21: r_matrix[i][j] = (j > i) ? dotProduct : 0; // predication
22: }
23: }
24: }
25:
26: // continue...
27:
28: }
これで j ループが完全に展開されました。依存関係がないため、4イタレーションすべてが同時に実行されます。
詳しくは、resource_sharing_filter チュートリアルを参照してください。このチュートリアルの場所は次のとおりです。 <quartus_installdir>/hls/examples/tutorials/best_practices/resource_sharing_filter
続行して、ループの展開を10行目ですることもできますが、このループを展開すると、面積が再び増加します。コンパイラーで、このループを展開するのではなく、パイプライン処理できるようにすると、面積の増加が回避でき、さらに使うのは約4クロックサイクルのみになります ( i ループのIIが1のみの場合)。ハイレベルのデザインレポートのLoops Analysis (report.html ) の詳細ペインには、この改善方法のヒントが表示されます。
- ループ搬送依存関係
<quartus_installdir>/hls/examples/tutorials/best_practices/loop_memory_dependency にあるチュートリアルを参照してください。
- 長いクリティカル・ループ・パス
- ループII > 1の内側のループ