インテルのみ表示可能 — GUID: mwh1391807502532
Ixiasoft
6.2. カーネルのベクトル化
カーネルの本体を変更せずに、Work-Itemごとに追加の実行をオフライン・コンパイラーに指示するには、カーネルコードにnum_simd_work_items属性を含めます。次のコードは、ベクトル化係数4を元のカーネルコードに適用します。
__attribute__((num_simd_work_items(4))) __attribute__((reqd_work_group_size(64,1,1))) __kernel void sum (__global const float * restrict a, __global const float * restrict b, __global float * restrict answer) { size_t gid = get_global_id(0); answer[gid] = a[gid] + b[gid]; }
num_simd_work_items属性を使用するには、reqd_work_group_size属性を使用してカーネルの必要なワーク・グループ・サイズを指定する必要があります。reqd_work_group_sizeに指定したワークグループのサイズは、num_simd_work_itemsに割り当てる値で割り切れなければなりません。上記のコード例では、カーネルの作業グループサイズは64であり、ワークグループは固定されています。各ワークグループ内で、Work-Itemは4つのSIMDベクタレーンに均等に分散されます。オフライン・コンパイラーが4つのSIMDベクタレーンを実装した後、各Work-Itemは4倍の作業を実行するようになりました。
オフライン・コンパイラーはコードをベクトル化し、メモリーアクセスを結合する可能性があります。オフライン・コンパイラーはこれらの最適化を自動的に適用するため、カーネルコードまたはホストコードを変更する必要はありません。
カーネルコードを手動でベクトル化できますが、実装するベクトル化の量を反映するように、ホスト・アプリケーションのNDRangeを調整する必要があります。次の例は、カーネル内で動作を手動で複製するときのコードの変更を示しています。
__kernel void sum (__global const float * restrict a, __global const float * restrict b, __global float * restrict answer) { size_t gid = get_global_id(0); answer[gid * 4 + 0] = a[gid * 4 + 0] + b[gid * 4 + 0]; answer[gid * 4 + 1] = a[gid * 4 + 1] + b[gid * 4 + 1]; answer[gid * 4 + 2] = a[gid * 4 + 2] + b[gid * 4 + 2]; answer[gid * 4 + 3] = a[gid * 4 + 3] + b[gid * 4 + 3]; }
この形式では、カーネルは配列aとbから4つの要素を読み出し、合計を計算し、その結果を配列のanswerに格納します 。 FPGAパイプラインはメモリー内の隣接する場所にデータをロードして格納するため、手動でオフライン・コンパイラーに4つのロードおよびストア動作の各グループを結合させることができます。