pragma HLS dependence - 2019.2 Japanese

Vitis 統合ソフトウェア プラットフォームの資料: アプリケーション アクセラレーション開発 (UG1393)

Document ID
UG1393
Release Date
2020-02-28
Version
2019.2 Japanese

説明

DEPENDENCE プラグマは、ループ運搬依存を克服し、ループをパイプライン処理できるようにする (またはより短い間隔でパイプラインできるようにする) ための追加情報を提供します。

Vivado HLS ツールでは、自動的に次の依存が検出されます。

  • ループ内 (ループ独立依存)。
  • 同じループの反復間 (ループ運搬依存)。

こうした依存は、演算をスケジューリングするタイミング、特に関数およびループのパイプライン処理に影響します。

ループ独立依存
同じ要素が同じループ反復でアクセスされます。
for (i=0;i<N;i++) {
 A[i]=x;
 y=A[i];
}
ループキャリー依存
同じ要素が異なるループ反復でアクセスされます。
for (i=0;i<N;i++) {
 A[i]=A[i-1]*2;
}

複雑な条件下では、自動依存性解析が保守的すぎ、偽依存性が除去されないことがあります。変数依存の配列インデックスや、外部要件を満たす必要があるような状況 (2 つの入力が同じインデックスにならない場合など) では、依存解析が保守的すぎることがあります。DEPENDENCE プラグマを使用すると、依存を明示的に指定し、偽依存を解決できます。

重要: 偽依存でないものを偽依存と指定すると、ハードウェアが正しく機能しなくなる可能性があります。依存性 (true または false) が正しいことを確認してから指定してください。

構文

依存が定義されている関数内に配置します。

#pragma HLS dependence variable=<variable> <class> \
<type> <direction> distance=<int> <dependent>

説明:

variable=<variable>
依存を考慮する変数を指定します (オプション)。
<class>
依存を明確にする必要がある変数のクラスを指定します (オプション)。有効な値は array または pointer です。
ヒント: 関数内で変数または変数のクラスのいずれかを指定していれば、<class> および variable= の両方を指定する必要はありません。
<type>
有効な値は intra または inter です。依存のタイプを指定します。
intra
同じループ反復内の依存。<type>intra<dependent> を false に設定すると、HLS ツールによりループ内で演算を自由に移動でき、パフォーマンスまたはエリアを向上できる可能性が高くなります。<dependent> を true に設定すると、演算を指定の順序で実行する必要があります。
inter
異なるループ反復間の依存。これがデフォルトの <type> です。<type> を inter<dependent> を false に設定すると、関数またはループがパイプライン処理されているか、ループが展開されていない場合または部分的に展開されている場合に、並列実行が可能になり、<dependent> を true に設定すると並列実行が不可能になります。
<direction>
有効な値は RAWWAR または WAW です。これはループ運搬依存にのみ関連し、依存の方向を指定します。
RAW
(Read-After-Write - 真の依存) 書き込み命令により書き込まれた値が読み出し命令で使用されます。
WAR
(Write-After-Read - 非依存) 読み出し命令により値が取得され、その値が書き込み命令で上書きされます。
WAW
(Write-After-Write - 出力依存): 2 つの書き込み命令により、特定の順序で同じロケーションに書き込みが実行されます。
distance=<int>
配列アクセスの反復間隔を指定します。これは、依存が true に設定されているループ運搬依存でのみ使用されます。
<dependent>
依存を使用する必要があるか (true)、削除するか (false) を指定します。デフォルトは true です。

例 1

次の例では、HLS ツールでは cols の値を認識する機能がないので、buff_A[1][col] への書き込みと buff_A[1][col] の読み出し間に常に依存性があると想定されます。このようなアルゴリズムでは、cols が 0 になることはほとんどありませんが、HLS ツールではデータ依存を想定できません。この依存を解決するため、DEPENDENCE プラグマを使用して、ループ反復間 (この例の場合は buff_Abuff_B の両方) に依存がないことを指定できます。

void foo(int rows, int cols, ...)
  for (row = 0; row < rows + 1; row++) {
    for (col = 0; col < cols + 1; col++) {
      #pragma HLS PIPELINE II=1
      #pragma HLS dependence variable=buff_A inter false
      #pragma HLS dependence variable=buff_B inter false
      if (col < cols) {
      buff_A[2][col] = buff_A[1][col]; // read from buff_A[1][col]
      buff_A[1][col] = buff_A[0][col]; // write to buff_A[1][col]
      buff_B[1][col] = buff_B[0][col];
      temp = buff_A[0][col];
}

例 2

次の例では、関数 fooloop_1 の同じ反復での Var1 の依存を削除しています。

#pragma HLS dependence variable=Var1 intra false

例 3

次の例では、関数 fooloop_2 にあるすべての配列の依存を定義し、同じループ反復ではすべての読み出しが書き込みの後に実行される (RAW) ように設定しています。

#pragma HLS dependence array intra RAW true