Поделиться через


Использование лямбда-выражений, объектов функций и ограниченных функций

Код C++ AMP, который требуется запустить в акселераторе, указывается в качестве аргумента в вызове parallel_for_each метода. Можно указать лямбда-выражение или объект функции (functor) в качестве этого аргумента. Кроме того, лямбда-выражение или объект функции может вызывать функцию C++ AMP-ограниченной. В этом разделе используется алгоритм добавления массива для демонстрации лямбда-объектов, объектов функций и ограниченных функций. В следующем примере показан алгоритм без кода C++ AMP. Создаются два 1-мерных массива равной длины. Соответствующие целые элементы добавляются и хранятся в третьем 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";
    }
}

Лямбда-выражение должно содержать один параметр индексирования и должен включать restrict(amp). В примере объект array_viewsum имеет ранг 1. Таким образом, параметр лямбда-инструкции является объектом индекса , который имеет ранг 1. Во время выполнения лямбда-выражение выполняется один раз для каждого элемента в объекте array_view . Дополнительные сведения см. в синтаксисе лямбда-выражения.

Объект 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";
    }
}

Объект-функция должен включать конструктор и должен включать перегрузку оператора вызова функции. Оператор вызова функции должен содержать один параметр индексирования. Экземпляр объекта функции передается в качестве второго аргумента методу parallel_for_each . В этом примере три объекта array_view передаются конструктору объектов-функции. Объект sum array_view имеет ранг 1. Таким образом, параметр для оператора вызова функции является объектом индекса , который имеет ранг 1. Во время выполнения функция выполняется один раз для каждого элемента в объекте array_view . Дополнительные сведения см. в разделе "Вызов функции" и "Объекты функций" в стандартной библиотеке C++.

Функция C++ AMP-Restricted

Кроме того, можно учитывать код акселератора, создав ограниченную функцию и вызвав ее из лямбда-выражения или объекта функции. В следующем примере кода показано, как вызвать ограниченную функцию из лямбда-выражения.

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) и соответствовать ограничениям, описанным в ограничении (C++ AMP).

См. также

C++ AMP (C++ Accelerated Massive Parallelism)
Синтаксис лямбда-выражений
Вызов функции
Объекты функции в стандартной библиотеке C++
restrict (C++ AMP)