Intel® FPGA SDK for OpenCL™: ベスト・プラクティス・ガイド

ID 683521
日付 12/08/2017
Public
ドキュメント目次

5.2. メモリー配列へのアクセスによるループキャリー依存関係の削除

単一のWork-Itemカーネルにivdepプラグマを含めて、メモリー配列へのアクセスがループに依存する依存関係を引き起こさないことを宣言します。
コンパイル中に、 Intel® FPGA SDK for OpenCL™オフライン・コンパイラーは、ロードおよびストア命令が依存関係の制約内で動作することを保証するハードウェアを作成します。依存関係制約の一例は、従属するロード命令およびストア命令が順番に実行されなければならないことです。 ivdepプラグマが存在すると、オフライン・コンパイラーは、カーネルコード内のプラグマ宣言の直後にあるループ内のロード命令とストア命令の間にこの余分なハードウェアを取り除くよう指示します。余分なハードウェアを削除すると、ロジック使用率が低下し、単一のWork-ItemカーネルでII値が低下する可能性があります。
  • ループ内にあるメモリー配列へのすべてのアクセスがループキャリー依存関係を引き起こさない場合、カーネルコードのループの前に#pragma ivdep行を追加します。
    Example kernel code:
    // no loop-carried dependencies for A and B array accesses
    #pragma ivdep
    for (int i = 0; i < N; i++) {
        A[i] = A[i - X[i]];
        B[i] = B[i - Y[i]];
    }
  • ループ内の特定のメモリー配列へのアクセスがループに依存する依存関係を引き起こさないように指定するには、カーネルコードのループの前に#pragma ivdep array( array_nameという行を追加します。

    ivdepプラグマで指定された配列は、ローカルまたはプライベートのメモリー配列、またはグローバル、ローカル、またはプライベートのメモリーストレージを指すポインター変数でなければなりません。指定された配列がポインターの場合、 ivdepプラグマは指定されたポインターで別名を持つ可能性があるすべての配列にも適用されます。

    ivdepプラグマで指定された配列は、構造体の配列またはポインターメンバーでもあります。

    カーネルコードの例 :

    // No loop-carried dependencies for A array accesses
    // The offline compiler will insert hardware that reinforces dependency constraints for B
    #pragma ivdep array(A)
    for (int i = 0; i < N; i++) {
        A[i] = A[i - X[i]];
        B[i] = B[i - Y[i]];
    }
    
    // No loop-carried dependencies for array A inside struct
    #pragma ivdep array(S.A)
    for (int i = 0; i < N; i++) {
        S.A[i] = S.A[i - X[i]];
    }
    
    // No loop-carried dependencies for array A inside the struct pointed by S
    #pragma ivdep array(S->X[2][3].A)
    for (int i = 0; i < N; i++) {
        S->X[2][3].A[i] = S.A[i - X[i]];
    }
    
    // No loop-carried dependencies for A and B because ptr aliases
    // with both arrays
    int *ptr = select ? A : B;
    #pragma ivdep array(ptr)
    for (int i = 0; i < N; i++) {
        A[i] = A[i - X[i]];
        B[i] = B[i - Y[i]];
    }
    
    // No loop-carried dependencies for A because ptr only aliases with A
    int *ptr = &A[10];
    #pragma ivdep array(ptr)
    for (int i = 0; i < N; i++) {
        A[i] = A[i - X[i]];
        B[i] = B[i - Y[i]];
    }