Condividi tramite


Utilizzo di espressioni lambda, oggetti funzione e funzioni con restrizioni

Il codice C++ AMP che si desidera eseguire sull'acceleratore viene specificato come argomento nella chiamata al metodo parallel_for_each. È possibile fornire una lambda espressione o un oggetto funzione (functor) come tale argomento. Inoltre, la lambda espressione o l'oggetto funzione possono chiamare una funzione C++ AMP limitata. In questo argomento viene utilizzato un algoritmo di somma di matrice per illustrare le funzioni lambda, gli oggetti funzione e le funzioni limitate. Nell'esempio riportato di seguito viene illustrato l'algoritmo senza codice C++ AMP. Vengono create due matrici monodimensionali di uguale lunghezza. Gli elementi integer corrispondenti vengono sommati e memorizzati in una terza matrice monodimensionale. C++ AMP non viene utilizzato.

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";
    }
}

Espressione lambda

Utilizzare una lambda espressione è il modo più diretto per usare C++ AMP per riscrivere il codice.

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";
    }
}

La lambda espressione deve includere un parametro di indicizzazione e deve includere restrict(amp). Nell'esempio, l'oggetto array_view sum ha rango uguale a 1. Di conseguenza, il parametro verso la lambda espressione è un oggetto indice con rango 1. In fase di esecuzione, l'espressione lambda viene eseguita una volta per ogni elemento dell'oggetto array_view. Per ulteriori informazioni, vedere Sintassi delle espressioni lambda.

Oggetto Function

È possibile scomporre il codice dell' acceleratore in un oggetto funzione.

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";
    }
}

L'oggetto funzione deve includere un costruttore e deve includere un overload dell'operatore di chiamata a funzione. L'operatore di chiamata a funzione deve includere un parametro indicizzante. Un'istanza dell'oggetto funzione viene passata come secondo argomento al metodo parallel_for_each. In questo esempio, tre oggetti array_view vengono passati al costruttore dell'oggetto funzione. L'oggetto sum array_view ha rango 1. Di conseguenza, il parametro dell'operatore chiamata a funzione è un oggetto index con rango 1. In fase di esecuzione, la funzione viene eseguita una volta per ogni elemento dell'oggetto array_view. Per ulteriori informazioni, vedere Chiamata di funzione (C++) e Oggetti funzione.

Funzione C++ AMP Limitata

È possibile scomporre ulteriormente il codice dell' acceleratore creando una funzione limitata e chiamandola da una lambda espressione o da un oggetto funzione. Nell'esempio di codice riportato di seguito viene illustrato come chiamare una funzione limitata a partire da una lambda espressione.

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";
    }
}

La funzione limitata deve includere restrict(amp) ed essere conforme alle limitazioni descritte in Clausola di restrizione (AMP C++).

Vedere anche

Riferimenti

Sintassi delle espressioni lambda

Chiamata di funzione (C++)

Clausola di restrizione (AMP C++)

Concetti

Oggetti funzione

Altre risorse

C++ AMP (C++ Accelerated Massive Parallelism)