インテル®高位合成 (HLS) コンパイラー プロ・エディション: ベスト・プラクティス・ガイド

ID 683152
日付 12/16/2019
Public
ドキュメント目次

4.4. ループ搬送依存関係の最小化

ループ搬送依存関係が発生するのは、ループ・イタレーション内のコードが、前のループ・イタレーションの出力に依存している場合です。コンポーネント内のループ搬送依存関係によってループ開始間隔 (II) が長くなります。これにより、コンポーネントのパフォーマンスが低下します。

次のループ構造にはループ搬送依存関係があります。これは、各ループ・イタレーションでは、前のイタレーションによって書き込まれたデータを読み出すためです。その結果、各読み出し動作の続行は、前のイタレーションからの書き込み動作が終了するまではできません。ループ搬送依存関係が存在すると、 インテル®HLSコンパイラー プロ・エディションによって達成できるパイプライン並列性を低下させます。これにより、カーネルのパフォーマンスが低下します。

for(int i = 1; i < N; i++)
{
    A[i] = A[i - 1] + i;
}

インテル®HLSコンパイラー プロ・エディションでは、スタティック・メモリー依存関係の解析をループで実行し、達成できる並列性の程度を判断します。 インテル®HLSコンパイラー プロ・エディションでは、ループ搬送依存関係がないと判断できない場合、ループ搬送依存関係は存在するとみなします。コンパイル時に未知の変数がある場合や、コード内の配列アクセスに複雑なアドレッシングが含まれる場合は、コンパイラーのループ搬送依存関係のテスト機能が妨げられます。

不要なループ搬送依存関係を回避し、コンパイラーによるループの解析が適切にできるようにするには、次のガイドラインに従います。

ポインター演算の回避

コンパイラーの出力が最適にならないのは、コンポーネントによる配列へのアクセスするために、算術演算から導出されたポインター値を逆参照する場合です。例えば、次のように配列へのアクセスを回避します。

for(int i = 0; i < N; i++)
{
    int t = *(A++);
    *A = t;
}

シンプルな配列インデックスの導入

複雑な配列インデックスの中には、効率的な解析ができないものがあります。これは、最適ではないコンパイラーの出力に繋がる可能性があります。次のような構造は、できるだけ避けてください。
  • 配列インデックスの非定数

    例えば、A[K + i] では、i はループ・インデックス変数、K は未知の変数です。

  • 同じサブスクリプト位置の複数のインデックス変数

    例えば、A[i + 2 × j] では、i および j は、二重ネスト化ループのループ・インデックス変数です。

    配列インデックス A[i][j] は、インデックス変数が異なるサブスクリプトであるため、効率的な解析ができます。

  • 非線形インデックス

    例えば、A[i & C] では、i はループ・インデックス変数で、C は定数または非定数の変数です。

定数の境界でのループの使用 (可能な場合)

コンパイラーによる範囲解析が効果的に実行できるのは、ループに定数の境界がある場合です。

if ステートメントをループ内に配置して、どのイタレーションでループ本体を実行するかを制御します。

ループ搬送依存関係の無視

ループ・イタレーション間で暗黙的なメモリー依存関係がない場合、 ivdep プラグマを使用して、可能性のあるメモリー依存関係を無視するように インテル®HLSコンパイラー プロ・エディションに指示します。

ivdep プラグマの使用方法の詳細については、 インテル®HLS (高位合成) コンパイラー: リファレンス・マニュアル内の ivdep プラグマを使用したループ搬送依存関係の削除を参照してください。