方法: 減少変数を使用する OpenMP ループを変換し、コンカレンシー ランタイムを使用する

この例では、reduction 句を使用する OpenMP parallel for ループを変換して、同時実行ランタイムを使用する方法を示します。

OpenMP reduction 句を使用すると、並列領域の最後にあるリダクション演算の対象となる 1 つ以上のスレッド プライベート変数を指定できます。 OpenMP には、リダクション演算子のセットがあらかじめ定義されています。 各リダクション変数はスカラー (intlongfloat など) にする必要があります。 OpenMP には、並列領域でのリダクション変数の使用方法に関する制限事項もいくつか定義されています。

並列パターン ライブラリ (PPL) には、concurrency::combinable クラスが用意されています。このクラスが提供する再利用可能なスレッドローカル記憶域を使用すると、詳細な計算を実行した後、それらの計算を最終結果にマージできます。 combinable クラスは、スカラー型と複合型の両方に作用するテンプレートです。 combinable クラスを使用するには、parallel コンストラクトの本体でサブ計算を実行してから、concurrency::combinable::combine メソッドまたは concurrency::combinable::combine_each メソッドを呼び出して最終結果を生成します。 combine メソッドと combine_each メソッドはそれぞれ、各要素ペアを結合する方法を指定する "combine 関数" を受け取ります。 したがって、combinable クラスは、リダクション演算子の固定セットだけに制限されません。

この例では、OpenMP とコンカレンシー ランタイムの両方を使用して、最初の 35 個のフィボナッチ数の合計を計算します。

// 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 からコンカレンシー ランタイムへの移行
並列コンテナーと並列オブジェクト