如何:将使用缩减变量的 OpenMP 循环转换为使用并发运行时

此示例介绍如何将使用 reduction 子句的 OpenMP parallelfor loop 转换为使用并发运行时。

OpenMP reduction 子句允许指定一个或多个线程专用变量,这些变量受并行区域末尾的缩减操作的约束。 OpenMP 预定义一组缩减运算符。 每个减量变量必须是标量(例如 intlongfloat)。 OpenMP 还定义了一些限制,说明如何在并行区域中使用缩减变量。

并行模式库 (PPL) 提供 concurrency::combinable 类,此类提供了可重用的线程本地存储,该存储允许你执行细化的计算,然后将这些计算合并为最终的结果。 类 combinable 是对标量和复杂类型执行操作的模板。 若要使用 combinable 类,请在并行构造的正文中执行子计算,然后调用 concurrency::combinable::combineconcurrency::combinable::combine_each 方法生成最终结果。 combinecombine_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 迁移至并发运行时
并行容器和对象