インテル® HLS コンパイラー: リファレンス・マニュアル

ID 683349
日付 6/23/2017
Public
ドキュメント目次

1.7.4. ivdep プラグマを使用したループ伝搬依存性の削除

コンポーネントをコンパイルする際、 HLSコンパイラーはロード / ストアー命令間のデータハザードを回避するためにハードウェアを生成します。特に、現在の反復がロード / ストアー命令の実行を終了する前にコンパイラーが新しいループ反復を開始しないようにするために、読み出しと書き込みの依存性はパフォーマンスを制限します。
HLSコンパイラーにはコード内にivdepプラグマを追加してコンポーネントのループ反復に依存しないことを保証するオプションがあります。
ivdepプラグマが存在すると、データハザードを回避するためにコンパイラーがハードウェアを生成することがなくなり、エリアを節約して影響を受けるループの II の値を低下させます。

ループ依存性に関する詳細は、safelen(N)クローズをivdepプラグマに追加することで取得できます。safelen(N)クローズはループ伝搬依存性のない連続ループ反復の最大数を指定します。例えば、#pragma ivdep safelen(32)はコンパイル時にループ伝搬依存性が導入される前に最大 32 回のループ反復があることをコンパイラーに示します。つまり、#pragma ivdepはこのループの反復間に暗黙的なメモリー依存性がないことを保証し、#pragma safelen(32)はこの反復に依存する可能性のある最も近い反復が 32 回の反復であることを保証します。

ループ内部の特定のメモリーアレイへのアクセスがループ伝搬依存性を引き起こさないように指定するには、コンポーネント・コードのループの前に#pragma ivdep array (array_name)行を追加します。ivdepプラグマで指定されたアレイは、ローカルまたはプライベートのメモリーアレイ、もしくはグローバル、ローカル、またはプライベートのメモリーストレージを指すポインター変数でなければなりません。指定されたアレイがポインターの場合、ivdepプラグマは指定されたポインターでエイリアスする可能性があるすべてのアレイにも適用されます。ivdepプラグマで指定されたアレイは、構造体のアレイまたはポインターメンバーでもあります。

注意:
ivdepプラグマを誤って使用すると、ハードウェアで機能エラーを起こす可能性があります。

使用ケース 1:

ループ内部のメモリーアレイへのすべてのアクセスがループ伝搬依存性を引き起こさない場合、ループの前に#pragma ivdepを追加します。

1  // no loop-carried dependencies for A and B array accesses
2  #pragma ivdep
3  for(int i = 0; i < N; i++) {
4      A[i] = A[i + N]; 
5      B[i] = B[i + N];
6  }

使用ケース 2:

#pragma ivdep array (array_name)はすべてのアレイアクセスに代わり、特定のメモリーアレイに指定できます。このプラグマはアレイ、ポインター、または構造体のポインターメンバーに適用されます。指定したアレイがポインターの場合、ivdepプラグマは指定したポインターでエイリアスする可能性のあるすべてのアレイに適用します。

 1  // No loop-carried dependencies for A array accesses
 2  // Compiler inserts hardware that reinforces dependency constraints for B
 3  #pragma ivdep array(A)
 4  for(int i = 0; i < N; i++) {
 5      A[i] = A[i - X[i]];
 6      B[i] = B[i - Y[i]];
 7  }
 8
 9  // No loop-carried dependencies for array A inside struct
10  #pragma ivdep array(S.A)
11  for(int i = 0; i < N; i++) {
12      S.A[i] = S.A[i - X[i]];
13  }
14
15  // No loop-carried dependencies for array A inside the struct pointed by S
16  #pragma ivdep array(S->X[2][3].A)
17  for(int i = 0; i < N; i++) {
18      S->X[2][3].A[i] = S.A[i - X[i]];
19  }
20
21  // No loop-carried dependencies for A and B because ptr aliases
22  // with both arrays
23  int *ptr = select ? A : B;
24  #pragma ivdep array(ptr)
25  for(int i = 0; i < N; i++) {
26      A[i] = A[i - X[i]];
27      B[i] = B[i - Y[i]];
28  }
29
30  // No loop-carried dependencies for A because ptr only aliases with A
31  int *ptr = &A[10];
32  #pragma ivdep array(ptr)
33  for(int i = 0; i < N; i++) {
34      A[i] = A[i - X[i]];
35      B[i] = B[i - Y[i]];
36  }