インテル® FPGA SDK for OpenCL™プロ・エディション: プログラミング・ガイド

ID 683846
日付 4/01/2019
Public
ドキュメント目次

5.12. 単一ワークアイテム・カーネルに向けた単一サイクル浮動小数点アキュムレーター

ループ内で累算を実行する単一ワークアイテム・カーネルは、 インテル® FPGA SDK for OpenCL™オフライン・コンパイラーの単一サイクル浮動小数点アキュムレーターの機能を活用することができます。 オフライン・コンパイラーはそれらのカーネルのインスタンスを探索し、ループで実行される累積をアキュムレーター構造へマッピングしようと試みます。

オフライン・コンパイラーは、値を加算または減算するアキュムレーターをサポートします。この機能を活用するには、オフライン・コンパイラーがアキュムレーターを推論できるように累算を記述します。

重要:
  • アキュムレーターは、Arria® 10デバイスでのみ利用可能です。
  • アキュムレーターはループの一部である必要があります。
  • アキュムレーターは初期値の0を持つ必要があります。
  • アキュムレーターを条件付きにすることはできません。

次は、オフライン・コンパイラーによる正しいアキュムレーターの推論をもたらす記述例です。

channel float4 RANDOM_STREAM;

__kernel void acc_test(__global float *a, int k) {
    // Simplest example of an accumulator.
    // In this loop, the accumulator acc is incremented by 5.
    int i;
    float acc = 0.0f;
    for (i = 0; i < k; i++) {
        acc+=5;
    }
    a[0] = acc;
}

__kernel void acc_test2(__global float *a, int k) {
    // Extended example showing that an accumulator can be
    // conditionally incremented. The key here is to describe the increment
    // as conditional, not the accumulation itself.
    int i;
    float acc = 0.0f;
    for (i = 0; i < k; i++) {
        acc += ((i < 30) ? 5 : 0);
    }
    a[0] = acc;
}

__kernel void acc_test3(__global float *a, int k) {
    // A more complex case where the accumulator is fed
    // by a dot product.
    int i;
    float acc = 0.0f;
    for (i = 0; i < k; i++ ){
        float4 v = read_channel_intel(RANDOM_STREAM);
        float x1 = v.x;
        float x2 = v.y;
        float y1 = v.z;
        float y2 = v.w;
 
        acc += (x1*y1+x2*y2);
    }
    a[0] = acc;
}

__kernel void loader(__global float *a, int k) {
    int i;
    float4 my_val = 0;
    for(i = 0; i < k; i++) {
        if ((i%4) == 0)
            write_channel_intel(RANDOM_STREAM, my_val);
        if ((i%4) == 0) my_val.x = a[i];
        if ((i%4) == 1) my_val.y = a[i];
        if ((i%4) == 2) my_val.z = a[i];
        if ((i%4) == 3) my_val.w = a[i];
    }
}