分享方式:


如何:轉換 OpenMP parallel for 迴圈來使用並行執行階段

此範例示範如何轉換使用 OpenMP 平行和 for 指示詞的基本迴圈,以使用並行執行時間 並行::p arallel_for 演算法。

範例 - 質數

這個範例同時使用 OpenMP 和並行執行時間來計算隨機值陣列中的質數計數。

// concrt-omp-count-primes.cpp
// compile with: /EHsc /openmp
#include <ppl.h>
#include <random>
#include <array>
#include <iostream>

using namespace concurrency;
using namespace std;

// Determines whether the input value is prime.
bool is_prime(int n)
{
   if (n < 2)
      return false;
   for (int i = 2; i < n; ++i)
   {
      if ((n % i) == 0)
         return false;
   }
   return true;
}

// Uses OpenMP to compute the count of prime numbers in an array.
void omp_count_primes(int* a, size_t size)
{
   if (size == 0)
      return;

   size_t count = 0;
   #pragma omp parallel for
      for (int i = 0; i < static_cast<int>(size); ++i)
      {
         if (is_prime(a[i])) {
            #pragma omp atomic
               ++count;
         }
      }

   wcout << L"found " << count 
         << L" prime numbers." << endl;
}

// Uses the Concurrency Runtime to compute the count of prime numbers in an array.
void concrt_count_primes(int* a, size_t size)
{
   if (size == 0)
      return;

   combinable<size_t> counts;
   parallel_for<size_t>(0, size, [&](size_t i) 
   {
      if (is_prime(a[i])) {
         counts.local()++;
      }
   });

   wcout << L"found " << counts.combine(plus<size_t>()) 
         << L" prime numbers." << endl;
}

int wmain()
{
   // The length of the array.
   const size_t size = 1000000;
   
   // Create an array and initialize it with random values.
   int* a = new int[size];
   
   mt19937 gen(42);
   for (size_t i = 0; i < size; ++i) {
      a[i] = gen();
   }

   // Count prime numbers by using OpenMP and the Concurrency Runtime.

   wcout << L"Using OpenMP..." << endl;
   omp_count_primes(a, size);

   wcout << L"Using the Concurrency Runtime..." << endl;
   concrt_count_primes(a, size);

   delete[] a;
}

此範例會產生下列輸出。

Using OpenMP...
found 107254 prime numbers.
Using the Concurrency Runtime...
found 107254 prime numbers.

演算法 parallel_for 和 OpenMP 3.0 允許索引類型成為帶正負號整數類型或不帶正負號的整數類型。 演算法 parallel_for 也會確保指定的範圍不會溢位帶正負號的類型。 OpenMP 2.0 和 2.5 版只允許帶正負號的整數索引類型。 OpenMP 也不會驗證索引範圍。

使用並行執行時間的這個範例版本也會使用 並行::combinable 物件取代 不可部分完成 指示詞來遞增計數器值,而不需要同步處理。

如需其他平行演算法的詳細資訊 parallel_for ,請參閱 平行演算法 。 如需 類別 combinable 的詳細資訊,請參閱 平行容器和物件

範例 - 使用 std::array

本範例會修改前一個物件,以在 std::array 物件上 執行動作,而不是在原生陣列上執行動作。 因為 OpenMP 2.0 和 2.5 版只允許建構中的 parallel_for 帶正負號整數索引類型,所以您無法使用反覆運算器平行存取 C++ 標準程式庫容器的元素。 平行模式程式庫 (PPL) 會在反復容器上提供 並行::p arallel_for_each 演算法,以平行方式在反復容器上執行工作,例如 C++ 標準程式庫所提供的工作。 它會使用演算法所使用的相同資料分割邏輯 parallel_for 。 此 parallel_for_each 演算法類似于 C++ 標準程式庫 std::for_each 演算法,但 parallel_for_each 演算法會同時執行工作。

// Uses OpenMP to compute the count of prime numbers in an 
// array object.
template<size_t Size>
void omp_count_primes(const array<int, Size>& a)
{
   if (a.size() == 0)
      return;

   size_t count = 0;
   int size = static_cast<int>(a.size());
   #pragma omp parallel for
      for (int i = 0; i < size; ++i)
      {
         if (is_prime(a[i])) {
            #pragma omp atomic
               ++count;
         }
      }

   wcout << L"found " << count 
         << L" prime numbers." << endl;
}

// Uses the Concurrency Runtime to compute the count of prime numbers in an 
// array object.
template<size_t Size>
void concrt_count_primes(const array<int, Size>& a)
{
   if (a.size() == 0)
      return;

   combinable<size_t> counts;
   parallel_for_each(begin(a), end(a), [&counts](int n) 
   {
      if (is_prime(n)) {
         counts.local()++;
      }
   });

   wcout << L"found " << counts.combine(plus<size_t>()) 
         << L" prime numbers." << endl;
}

編譯程式碼

複製範例程式碼,並將其貼到 Visual Studio 專案中,或貼到名為 concrt-omp-count-primes.cpp 的檔案中,然後在 Visual Studio 命令提示字元視窗中執行下列命令。

cl.exe /EHsc /openmp concrt-omp-count-primes.cpp

另請參閱

從 OpenMP 移轉至並行執行階段
平行演算法
平行容器和物件