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


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

Код C++ AMP, который должен выполняться на ускорителе, указывается в качестве аргумента при вызове метода parallel_for_each. В качестве этого аргумента можно предоставить или лямбда-выражение или объект функции (функтор). Кроме того, лямбда-выражение или объект функции могут вызвать ограниченную функцию C++ AMP. Этот раздел использует алгоритм сложения массивов для демонстрации лямбда-выражений, объектов функций и ограниченных функций. В следующем примере показан алгоритм без кода C++ AMP. Создаются два одномерных массива одинаковой длины. Соответствующие элементы целого типа добавляются и хранятся в третьем 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_view sum имеет размерность 1. Поэтому параметр в лямбда-выражении – объект index, имеющий ранг 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 передаются конструктору объекта функции. Объект array_viewsum имеет ранг 1. Поэтому параметр в операторе вызова функции – объект index, имеющий ранг 1. Во время выполнения функция выполняется один раз для каждого элемента в объекте array_view. Дополнительные сведения см. в разделах Вызов функций (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) и соответствовать ограничениям, описанным в Предложение ограничения (C++).

См. также

Ссылки

Синтаксис лямбда-выражений

Вызов функций (C++)

Предложение ограничения (C++)

Основные понятия

Объекты функций

Другие ресурсы

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