入れ子のループはコード記述で一般的に使用されます。入れ子のループ構造内のループがどのようにパイプライン処理されるか理解することが、必要なパフォーマンスの達成につながります。
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
制約を適用するのに役立ちます。
推奨: 外側のループの境界が変数の場合でも、コンパイラでループを平坦化することは可能です。内側のループの範囲は、定数にするようにしてください。