入れ子のループはコード記述で一般的に使用されます。必要なパフォーマンスを達成するには、入れ子のループ構造内のループがどのようにパイプライン処理されるかを理解することが重要です。
HLS PIPELINE プラグマを別のループ内に含まれるループに適用すると、v++
コンパイラはそのループを平坦化して 1 つのループを作成し、作成されたループに PIPELINE プラグマを適用します。ループを平坦化すると、カーネルのパフォーマンスが向上します。
コンパイラでは、次のタイプの入れ子のループを平坦化できます。
- 完全入れ子ループ:
- 内側のループのみにループ本体が含まれます。
- ループ宣言間に指定されるロジックまたは演算はありません。
- すべてのループ範囲は定数です。
- 半完全入れ子ループ:
- 内側のループのみにループ本体が含まれます。
- ループ宣言の間にはロジックまたは演算は指定されません。
- 内側のループ範囲は定数にする必要がありますが、外側のループ範囲は変数にできます。
次のコード例に、完全入れ子ループの構造を示します。
ROW_LOOP: for(int i=0; i< MAX_HEIGHT; i++) {
COL_LOOP: For(int j=0; j< MAX_WIDTH; j++) {
#pragma HLS PIPELINE
// Main computation per pixel
}
}
上記の例は、入力ピクセル データに対して計算を実行する 2 つのループを含む入れ子のループ構造を示します。ほとんどの場合、サイクルごとに 1 ピクセル処理するのが望ましいので、PIPELINE は入れ子のループの本体構造に適用されます。この例の場合は完全入れ子ループなので、コンパイラで入れ子ループ構造を平坦化できます。
上記の例の入れ子ループには、2 つのループ宣言の間にロジックは含まれていません。ROW_LOOP
と COL_LOOP
の間にロジックがないので、すべての処理ロジックが COL_LOOP
に含まれます。また、両方のループの反復数は固定されています。これら 2 つの条件を満たすことが、v++
コンパイラでループを平坦化し、PIPELINE 制約を適用するのに役立ちます。
推奨: 外側のループの境界が変数の場合でも、コンパイラでループを平坦化することは可能です。内側のループの範囲は、定数にする必要があります。