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

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

8.3. メモリーアクセスに関する考慮事項

インテル® メモリーアクセス効率を向上させ、 OpenCL™カーネルのエリア使用を削減するカーネル・プログラミング戦略を推奨しています。
  1. 外部メモリーへのアクセスポイントの数を最小限に抑えます。

    可能であれば、ある場所から入力を読み出し、内部的にデータを処理し、出力を別の場所に書き込むようにカーネルを構造化します。

  2. ローカルまたはグローバル・メモリー・アクセスに頼るのではなく、可能であればシフトレジスター推論を使ってカーネルをSingle Work-Itemとして構造化してください。
  3. 外部メモリーにデータを書き込むカーネルと外部メモリーからデータを読み込むカーネルを作成する代わりに、直接データ転送のためにカーネル間に インテル® FPGA SDK for OpenCL™ チャネル拡張を実装します。
  4. OpenCLアプリケーションは、多くの独立した定数データアクセスが含まれている場合、代わりに__global const__constant使用して対応するポインターを宣言します。 __global constを使用する宣言は、ロードまたはストア動作ごとにプライベート・キャッシュを作成します。一方、 __constantを使用した宣言では、単一の定数キャッシュがチップ上にのみ作成されます。
    注意:
    カーネルがCyclone® Vデバイス(たとえば、Cyclone V SoC)をターゲットにしている場合、 __constantポインターカーネル引数を宣言すると、FPGAのパフォーマンスが低下する可能性があります。

  5. カーネルが少数の定数引数を渡した場合、それらをグローバルメモリーへのポインターではなく値として渡します。

    例えば、代わり* COEF __constant INTを通過した後、10にインデックス0を有するCOEFを間接参照の値(INT16のCOEF)としてCOEFを渡します。 coef__constantポインターの唯一の引数だった場合、それを値として渡すと、定数キャッシュとそれに対応するロードとストア動作が完全に削除されます。

  6. パイプライン・ループ内で大規模なシフトレジスターを条件付きでシフトすると、効率の悪いハードウェアが作成されます。たとえば、 if(K> 5)条件が存在する場合 、次のカーネルはより多くのリソースを消費します。
    #define SHIFT_REG_LEN 1024
    __kernel void bad_shift_reg (__global int * restrict src,
                                 __global int * restrict dst,
                                 int K)
    {
        float shift_reg[SHIFT_REG_LEN];
        int sum = 0;
     
        for (unsigned i = 0; i < K; i++)
        {
            sum += shift_reg[0];
            shift_reg[SHIFT_REG_LEN-1] = src[i];
    
            // This condition will cause sever area bloat.
            if (K > 5)
            {
              #pragma unroll
              for (int m = 0; m < SHIFT_REG_LEN-1 ; m++)
              {
                  shift_reg[m] = shift_reg[m + 1];
              }
            }
            dst[i] = sum;
        }
    }
    重要: 条件付きでシフトレジスターにアクセスしても、ハードウェアの効率は低下しません。 カーネルに大きなシフトレジスターの条件付きシフトを実装する必要がある場合は、ローカルメモリーを使用するようにコードを変更することを検討してください。