Использование лямбда-выражений, объектов функций и ограниченных функций
Код 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++).