pragma HLS unroll - 2023.2 日本語

Vitis 高位合成ユーザー ガイド (UG1399)

Document ID
UG1399
Release Date
2023-12-18
Version
2023.2 日本語

説明

ループを展開すると、複数の演算を 1 つにまとめたものではなく、複数の個別の演算を作成できます。UNROLL プラグマを使用すると、RTL デザインにループ本体のコピーを複数作成することにより、一部またはすべてのループ反復を並列実行できるようになります。

C/C++ 関数のループは、デフォルトでは展開されません。ループが展開されていない場合、合成ではそのループの 1 反復に対してロジックが作成され、RTL デザインでこのロジックがループの反復ごとに順に実行されます。ループは、ループ帰納変数で指定されている反復回数実行されます。反復の回数は、break 条件やループ exit 変数の変更など、ループ本体内のロジックにも影響されます。UNROLL プラグマを使用すると、データのアクセスおよびスループットを向上するためにループを展開できます。

UNROLL プラグマでは、ループを完全にまたは部分的に展開できます。ループを完全に展開すると、RTL に各ループ反復対してループ本体のコピーが作成され、ループ全体を同時に実行できるようになります。ループの部分展開では、係数 N を指定してループのコピーを N 個作成し、ループ反復数を削減します。

ヒント: ループを完全に展開するには、ループの境界がコンパイル時に認識される必要があります。これは部分展開には必要ありません。

ループを部分展開する場合、N は最大反復回数の整数因数である必要はありません。Vitis HLS ツールでは、部分展開されたループが元のループと同じように動作することを確認する終了チェックが追加されます。たとえば、次のようなコードがあるとします。

for(int i = 0; i < X; i++) {
  pragma HLS unroll factor=2
  a[i] = b[i] + c[i];
}
ループを係数 2 で展開すると、コードが次のように変換されます。このコードでは、break コンストラクトにより機能が同じになり、ループが適切なポイントで終了します。
for(int i = 0; i < X; i += 2) {
  a[i] = b[i] + c[i];
  if (i+1 >= X) break;
  a[i+1] = b[i+1] + c[i+1];
}

上記の例では最大反復回数 X は変数なので、HLS ツールでその値を判断できず、部分展開されるループに終了チェックと制御ロジックが追加されます。ただし、展開係数 (この例では 2) が最大反復回数 X の整数因数であるとわかっている場合は、skip_exit_check オプションを使用して終了チェックとその関連ロジックを削除できます。これによりエリアが最小限に抑えられ、制御ロジックが単純になります。

ヒント: ARRAY_PARTITION または ARRAY_RESHAPE などのプラグマの使用により 1 クロック サイクルでより多くのデータにアクセスできるようになっている場合、このデータを消費するループを展開することによりスループットが向上するのであれば、HLS ツールでこれらのループが自動的に展開されます。ループを完全または部分展開すると、1 クロック サイクルでこれらの追加データを消費するのに十分なハードウェアを作成できます。この自動展開機能は、config_unroll コマンドを使用して制御します。

構文

C ソースの展開するループの本体内に配置します。

#pragma HLS unroll factor=<N> skip_exit_check off=true

説明:

factor=<N>
以外の整数値を指定して、部分展開が実行されるようにします。ループの本体が指定した回数繰り返され、反復情報がそれに合わせて調整されます。factor= を指定しない場合、ループは完全に展開されます。
skip_exit_check
factor= を使用して部分展開を指定している場合にのみ適用されるオプションのキーワードです。ループの反復回数が既知であるかどうかによって、終了チェックが削除されます。
  • 固定境界

    反復回数が係数の倍数である場合は、終了条件はチェックされません。

    反復回数が係数の整数倍でない場合は、次のようになります。

    • 展開は実行されません。
    • 処理を続行するには終了チェックを実行する必要があることを示す警告メッセージが表示されます。
  • 可変境界

    終了条件チェックが削除されます。次を確認してください。

    • 可変境界が係数の整数倍である。
    • 終了チェックが不要である。
off=true
指定されたループの展開を無効にします。

例 1

次の例では、関数 foo 内の loop_1 を完全に展開しています。プラグマを loop_1 の本体に記述します。

loop_1: for(int i = 0; i < N; i++) {
  #pragma HLS unroll
  a[i] = b[i] + c[i];
}

例 2

次の例では、関数 fooloop_2 を係数 4 で部分展開し、終了チェックを削除しています。

void foo (...) {
  int8 array1[M];
  int12 array2[N];
  ...
  loop_2: for(i=0;i<M;i++) {
    #pragma HLS unroll skip_exit_check factor=4
    array1[i] = ...;  
    array2[i] = ...;
    ...
  }
  ...
}