Практическое руководство. Преобразование цикла OpenMP, использующего переменную сокращения для использования среды выполнения с параллелизмом
В этом примере показано, как преобразовать для использования среды выполнения с параллелизмом цикл parallelfor OpenMP, использующий предложение снижение.
Предложение reduction OpenMP позволяет задавать одну или несколько переменных, закрытых в определенных потоках, к которым в конце параллельной области применяется операция редукции.OpenMP предопределяет набор операторов редукции.Все переменные редукции должны быть скалярными (например, int, long и float).OpenMP также определяет несколько ограничений на использование переменных редукции в параллельной области.
Параллельные шаблоны (PPL) обеспечивает concurrency::combinable класс, который предоставляет хранилище для многократного использования, локальной памяти потока, позволяет выполнять вычисления детализированное и затем объединить эти вычисления конечного результата.Класс combinable — это шаблон, работающий как со скалярными, так и со сложными типами.Использование combinable класса, выполнение sub-computations в теле параллельной конструкции и затем вызвать concurrency::combinable::combine или concurrency::combinable::combine_each метод для получения окончательного результата.Методы combine и combine_each принимают функцию combine, которая указывает, как объединять пары элементов.Поэтому класс combinable не ограничен определенным набором операторов редукции.
Пример
В этом примере для вычисления суммы первых 35 чисел Фибоначчи используется как OpenMP, так и среда выполнения с параллелизмом.
// concrt-omp-fibonacci-reduction.cpp
// compile with: /EHsc /openmp
#include <ppl.h>
#include <iostream>
using namespace concurrency;
using namespace std;
// Computes the nth Fibonacci number.
// This function illustrates a lengthy operation and is therefore
// not optimized for performance.
int fibonacci(int n)
{
if (n < 2)
return n;
// Compute the components in parallel.
int n1, n2;
parallel_invoke(
[n,&n1] { n1 = fibonacci(n-1); },
[n,&n2] { n2 = fibonacci(n-2); }
);
return n1 + n2;
}
// Uses OpenMP to compute the sum of Fibonacci numbers in parallel.
void omp_parallel_fibonacci_sum(int count)
{
int sum = 0;
#pragma omp parallel for reduction(+ : sum)
for (int i = 0; i < count; ++i)
{
sum += fibonacci(i);
}
wcout << L"The sum of the first " << count << L" Fibonacci numbers is "
<< sum << L'.' << endl;
}
// Uses the Concurrency Runtime to compute the sum of Fibonacci numbers in parallel.
void concrt_parallel_fibonacci_sum(int count)
{
combinable<int> sums;
parallel_for(0, count, [&sums](int i)
{
sums.local() += fibonacci(i);
});
wcout << L"The sum of the first " << count << L" Fibonacci numbers is "
<< sums.combine(plus<int>()) << L'.' << endl;
}
int wmain()
{
const int count = 35;
wcout << L"Using OpenMP..." << endl;
omp_parallel_fibonacci_sum(count);
wcout << L"Using the Concurrency Runtime..." << endl;
concrt_parallel_fibonacci_sum(count);
}
В результате выполнения примера получается следующий результат:
Using OpenMP...
The sum of the first 35 Fibonacci numbers is 14930351.
Using the Concurrency Runtime...
The sum of the first 35 Fibonacci numbers is 14930351.
Дополнительные сведения о классе combinable см. в разделе Параллельные контейнеры и объекты.
Компиляция кода
Скопируйте код и вставьте его в проект Visual Studio или вставьте его в файл с именем concrt omp Фибоначчи reduction.cpp и запустите следующую команду в окне командной строки Visual Studio.
cl.exe /EHsc /openmp concrt-omp-fibonacci-reduction.cpp