前回は行列積演算の回路を用いて、パイプラインディレクティブの効果を測定した。 次はループアンローリングの効果を測定してみる。Vivado HLSにはUNROLLディレクティブが存在するため、こちらを行列積演算回路のループに適用して、どの程度効果があるのかを見てみる。
基本となるのは、前回と同様の行列積演算回路だ。
for (int j = 0; j < MATRIX_LENGTH; j++) { for (int i = 0; i < MATRIX_LENGTH; i++) { matrix_c[j][i] = 0; for (int k = 0; k < MATRIX_LENGTH; k++) { matrix_c[j][i] += matrix_a[j][k] * matrix_b[k][i]; } } }
これに対し、最内ループにUNROLLディレクティブを適用してみた。
あれ?PIPELINEディレクティブも一緒に追加されている。良く分からないが、このまま進めてみる。
前回と同様に実行した結果、最内ループをアンロールした場合には、最内ループをパイプライン化した場合とほぼ同様のサイクル数となった。
種類 | Vivado HLSサイクル数見積 | (実測)サイクル数(20回実行) | サイクル数(平均) |
---|---|---|---|
パイプライン化無し | 2629762 | 5486812 | 274340.6 |
最内ループ パイプライン | 1343488 | 2807102 | 140355.1 |
最内ループ 2番目ループ パイプライン | 262407 | 554837 | 27741.85 |
最内ループ 2番目ループ 最外ループ パイプライン | 取得忘れ | 計測未 | - |
最内ループ アンローリング(今回計測) | 1335425 | 2790294 | 139514.7 |
また、LUTの使用率は以下のようになった。使用率は非常に低く、ほぼ誤差の範囲と言ってよい。
+----------------------------+------+-------+-----------+-------+ | Site Type | Used | Fixed | Available | Util% | +----------------------------+------+-------+-----------+-------+ | Slice LUTs* | 1823 | 0 | 53200 | 3.43 | | LUT as Logic | 1753 | 0 | 53200 | 3.30 | | LUT as Memory | 70 | 0 | 17400 | 0.40 | | LUT as Distributed RAM | 0 | 0 | | | | LUT as Shift Register | 70 | 0 | | | | Slice Registers | 1967 | 0 | 106400 | 1.85 | | Register as Flip Flop | 1967 | 0 | 106400 | 1.85 | | Register as Latch | 0 | 0 | 106400 | 0.00 | | F7 Muxes | 0 | 0 | 26600 | 0.00 | | F8 Muxes | 0 | 0 | 13300 | 0.00 | +----------------------------+------+-------+-----------+-------+
次に、2番目のループにもアンローリングを適用し、同様に効果を測定した。2番目のループにアンローリングを適用すると、これまでSynthesisがほぼ瞬殺だったのが、結構時間がかかるようになった。 約10分くらい?
そして結果。動作周波数が100MHzを割ってしまった。
動作サイクルの見積としては、かなり小さくなっている。これを合成して実行することができるか?
結果、2時間経過してもまだ合成が終了しない。とりあえず、急激に合成時間が増えたので今回は計測対象外とする。
結論: 何でもやりすぎは禁物。