Практическое руководство. Преобразование цикла OpenMP, использующего переменную сокращения для использования среды выполнения с параллелизмом

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

Предложение OpenMP reduction позволяет указать одну или несколько частных переменных потока, которые подвергаются операции уменьшения в конце параллельного региона. OpenMP предопределяет набор операторов сокращения. Каждая переменная сокращения должна быть скалярной (например, int, longи float). OpenMP также определяет несколько ограничений на использование переменных сокращения в параллельном регионе.

Библиотека параллельных шаблонов (PPL) предоставляет класс параллелизма::комбинируемый класс, предоставляющий повторное использование, локальное хранилище потоков, которое позволяет выполнять точные вычисления, а затем объединять эти вычисления в окончательный результат. Класс combinable — это шаблон, который действует как на скалярных, так и на сложных типах. Чтобы использовать combinable класс, выполните вложенные вычисления в теле параллельной конструкции, а затем вызовите метод параллелизма::combineable::combine or concurrency::combineable::combinable::combine_each , чтобы получить окончательный результат. Методы combine и combine_each методы принимают функцию объединения, которая указывает, как объединить каждую пару элементов. combinable Поэтому класс не ограничен фиксированным набором операторов сокращения.

Пример

В этом примере используется OpenMP и среда выполнения параллелизма для вычисления суммы первых 35 чисел Fibonacci.

// 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-fibonacci-reduction.cpp , а затем выполните следующую команду в окне командной строки Visual Studio.

cl.exe /EHsc /openmp concrt-omp-fibonacci-reduction.cpp

См. также

Переход от OpenMP к среде выполнения с параллелизмом
Параллельные контейнеры и объекты