Gör så här: Konvertera en OpenMP-parallell loop för att använda Concurrency Runtime

Det här exemplet visar hur du konverterar en grundläggande loop som använder OpenMP parallel och for-direktiv för att använda Concurrency Runtime concurrency::parallel_for-algoritmen.

Exempel – primtal

I det här exemplet används både OpenMP och Concurrency Runtime för att beräkna antalet primära tal i en matris med slumpmässiga värden.

// 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;
}

Det här exemplet genererar följande utdata.

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

Algoritmen parallel_for och OpenMP 3.0 tillåter att indextypen är en signerad integraltyp eller en osignerad integraltyp. Algoritmen parallel_for ser också till att det angivna intervallet inte spiller över en signerad typ. OpenMP-versionerna 2.0 och 2.5 tillåter endast signerade integralindextyper. OpenMP validerar inte heller indexintervallet.

Den version av det här exemplet som använder Concurrency Runtime använder också ett samtidighetsobjekt::combinable-objekt i stället för atomdirektivet för att öka räknarvärdet utan att kräva synkronisering.

Mer information om parallel_for och andra parallella algoritmer finns i Parallella algoritmer. Mer information om klassen finns i combinableParallella containrar och objekt.

Exempel – använd std::array

I det här exemplet ändras det tidigare objektet så att det fungerar på ett std::array-objekt i stället för på en intern matris. Eftersom OpenMP-versionerna 2.0 och 2.5 endast tillåter signerade integralindextyper i en parallel_for konstruktion kan du inte använda iteratorer för att komma åt elementen i en C++ Standard Library-container parallellt. Det parallella mönsterbiblioteket (PPL) tillhandahåller algoritmen concurrency::p arallel_for_each , som utför uppgifter parallellt på en iterativ container, till exempel de som tillhandahålls av C++-standardbiblioteket. Den använder samma partitioneringslogik som algoritmen parallel_for använder. Algoritmen parallel_for_each liknar C++ Standard Library std::for_each-algoritmen , förutom att algoritmen parallel_for_each kör uppgifterna samtidigt.

// 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;
}

Kompilera koden

Kopiera exempelkoden och klistra in den i ett Visual Studio-projekt, eller klistra in den i en fil med namnet concrt-omp-count-primes.cpp och kör sedan följande kommando i ett Visual Studio-kommandotolkfönster.

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

Se även

Migrera från OpenMP till Concurrency Runtime
Parallella algoritmer
parallella containrar och objekt