次の方法で共有


ラムダ、関数オブジェクト、および制限付き関数の使用

アクセラレータで実行する C++ AMP コードは、 parallel_for_each メソッドの呼び出しで引数として指定されます。 ラムダ式または関数オブジェクト (ファンクター) をその引数として指定できます。 さらに、ラムダ式または関数オブジェクトは、C++ AMP 制限付き関数を呼び出すことができます。 このトピックでは、配列加算アルゴリズムを使用して、ラムダ、関数オブジェクト、および制限付き関数を示します。 次の例は、C++ AMP コードのないアルゴリズムを示しています。 等しい長さの 2 つの 1 次元配列が作成されます。 対応する整数要素が追加され、3 番目の 1 次元配列に格納されます。 C++ AMP は使用されません。

void CpuMethod() {

    int aCPP[] = {1, 2, 3, 4, 5};
    int bCPP[] = {6, 7, 8, 9, 10};
    int sumCPP[5];

    for (int idx = 0; idx <5; idx++)
    {
        sumCPP[idx] = aCPP[idx] + bCPP[idx];
    }

    for (int idx = 0; idx <5; idx++)
    {
        std::cout <<sumCPP[idx] <<"\n";
    }
}

ラムダ式

ラムダ式を使用することは、C++ AMP を使用してコードを書き直す最も直接的な方法です。

void AddArraysWithLambda() {
    int aCPP[] = {1, 2, 3, 4, 5};
    int bCPP[] = {6, 7, 8, 9, 10};
    int sumCPP[5];

    array_view<const int, 1> a(5, aCPP);

    array_view<const int, 1> b(5, bCPP);

    array_view<int, 1> sum(5, sumCPP);

    sum.discard_data();

    parallel_for_each(
        sum.extent,
        [=](index<1> idx) restrict(amp)
        {
             sum[idx] = a[idx] + b[idx];
        });

    for (int i = 0; i <5; i++) {
        std::cout <<sum[i] <<"\n";
    }
}

ラムダ式には、1 つのインデックス作成パラメーターを含める必要があり、 restrict(amp)を含める必要があります。 この例では、 array_viewsum オブジェクトのランクは 1 です。 したがって、ラムダ ステートメントのパラメーターは、ランク 1 の インデックス オブジェクトです。 実行時に、ラムダ式は 、array_view オブジェクト内の各要素に対して 1 回実行されます。 詳細については、「 ラムダ式の構文」を参照してください。

Function オブジェクト

アクセラレータ コードを関数オブジェクトに組み込むことができます。

class AdditionFunctionObject
{
public:
    AdditionFunctionObject(const array_view<int, 1>& a,
    const array_view<int, 1>& b,
    const array_view<int, 1>& sum)
    : a(a), b(b), sum(sum)
    {
    }

    void operator()(index<1> idx) restrict(amp)
    {
        sum[idx] = a[idx] + b[idx];
    }

private:
    array_view<int, 1> a;
    array_view<int, 1> b;
    array_view<int, 1> sum;
};

void AddArraysWithFunctionObject() {
    int aCPP[] = {1, 2, 3, 4, 5};
    int bCPP[] = {6, 7, 8, 9, 10};
    int sumCPP[5];

    array_view<const int, 1> a(5, aCPP);

    array_view<const int, 1> b(5, bCPP);

    array_view<int, 1> sum(5, sumCPP);

    sum.discard_data();

    parallel_for_each(
        sum.extent,
        AdditionFunctionObject(a, b, sum));

    for (int i = 0; i <5; i++) {
        std::cout <<sum[i] <<"\n";
    }
}

関数オブジェクトにはコンストラクターを含める必要があり、関数呼び出し演算子のオーバーロードを含める必要があります。 関数呼び出し演算子には、1 つのインデックス作成パラメーターを含める必要があります。 関数オブジェクトのインスタンスは、 parallel_for_each メソッドに 2 番目の引数として渡されます。 この例では、3 つの array_view オブジェクトが関数オブジェクト コンストラクターに渡されます。 array_view オブジェクト sumのランクは 1 です。 したがって、関数呼び出し演算子のパラメーターは、ランク 1 の インデックス オブジェクトです。 実行時に、関数は 、array_view オブジェクト内の各要素に対して 1 回実行されます。 詳細については、関数呼び出しC++ 標準ライブラリにおける関数オブジェクトを参照してください。

"C++ AMP-リストリクテッド" 関数

制限付き関数を作成し、ラムダ式または関数オブジェクトから呼び出すことで、アクセラレータ コードをさらに考慮できます。 次のコード例は、ラムダ式から制限付き関数を呼び出す方法を示しています。

void AddElementsWithRestrictedFunction(index<1> idx, array_view<int, 1> sum, array_view<int, 1> a, array_view<int, 1> b) restrict(amp)
{
    sum[idx] = a[idx] + b[idx];
}

void AddArraysWithFunction() {

    int aCPP[] = {1, 2, 3, 4, 5};
    int bCPP[] = {6, 7, 8, 9, 10};
    int sumCPP[5];

    array_view<int, 1> a(5, aCPP);

    array_view<int, 1> b(5, bCPP);

    array_view<int, 1> sum(5, sumCPP);

    sum.discard_data();

    parallel_for_each(
        sum.extent,
        [=](index<1> idx) restrict(amp)
        {
            AddElementsWithRestrictedFunction(idx, sum, a, b);
        });

    for (int i = 0; i <5; i++) {
        std::cout <<sum[i] <<"\n";
    }
}

制限付き関数には、 restrict(amp) を含め、 restrict (C++ AMP) で説明されている制限に準拠する必要があります。

こちらも参照ください

C++ AMP (C++ Accelerated Massive Parallelism)
ラムダ式の構文
関数呼び出し
C++ 標準ライブラリの関数オブジェクト
restrict (C++ AMP)