pragma HLS dependence - 2023.2 日本語

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

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

説明

Vitis HLS では、ループの同じ反復内での依存 (ループ独立依存) と、ループの異なる反復間の依存 (ループ運搬依存) が検出されます。DEPENDENCE プラグマを使用すると、追加の情報を定義、ループ依存を無効化、ループをより短い間隔でパイプライン処理できます。

ループ独立依存
同じ要素が 1 つのループ反復内でアクセスされます。
for (i=1;i<N;i++) {
 A[i]=x;
 y=A[i];
}
ループ運搬依存
同じ要素が異なるループ反復からアクセスされます。
for (i=1;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>
依存を考慮する変数を指定します (オプション)。
重要: 関数引数が m_axi インターフェイスでほかの引数とバンドルでまとめられている場合は、その関数引数に dependence を指定できません。これは、関数の m_axi インターフェイスのデフォルト設定です。また、構造体が分割されていない場合、構造体の要素に依存は指定できません。
class=[array | pointer]
依存を明確にする必要がある変数のクラスを指定します (オプション)。有効な値は array または pointer です。
ヒント: 1 つの変数または関数内の変数のクラスの依存は指定できるので、<class>variable= は一緒に指定するべきではありません。
type=[inter | intra]
有効な値は intra または inter です。依存のタイプを指定します。
intra
同じループ反復内の依存。<type>intra<dependent> を false に設定すると、HLS ツールによりループ内で演算を自由に移動でき、パフォーマンスまたはエリアを向上できる可能性が高くなります。<dependent> を true に設定すると、演算を指定の順序で実行する必要があります。
inter
異なるループ反復間の依存。これがデフォルトの <type> です。<type> を inter<dependent> を false に設定すると、関数またはループがパイプライン処理されているか、ループが展開されていない場合または部分的に展開されている場合に、並列実行が可能になり、<dependent> を true に設定すると並列実行が不可能になります。
direction=[RAW | WAR | WAW]
これはループ運搬依存にのみ関連し、依存の方向を指定します。
RAW (Read-After-Write - 真の依存)
書き込み命令により値が書き込まれ、その値が読み出し命令で使用されます。
WAR (Write-After-Read - アンチ依存)
読み出し命令で値が取得され、その値が書き込み命令で上書きされます。
WAW (Write-After-Write - 出力依存)
2 つの書き込み命令により、特定の順序で同じロケーションに書き込みが実行されます。
distance=<int>
配列アクセスの反復間隔を指定します。これは、依存が true に設定されているループ運搬依存でのみ使用されます。
<dependent>
<dependent> 引数には依存を使用する必要があるか (true)、削除するか (false) を指定します。指定しない場合、値が指定されていないことを示す警告メッセージが表示され、false が指定されているのと同様に処理されます。使用できる値は true または false です。

例 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 type=inter false
    #pragma HLS dependence variable=buff_B type=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];
      }
    }
  }
}

例 2

次の例は、関数 funcloop_1 の同じ反復内での Var1 間の依存を削除します。

#pragma HLS dependence variable=Var1 type=intra false

例 3

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

#pragma HLS dependence class=array type=intra direction=RAW true