Freigeben über


Gewusst wie: Konvertieren einer parallel-for-Schleife in OpenMP zur Verwendung der Concurrency Runtime

In diesem Beispiel wird veranschaulicht, wie eine einfache Schleife zu konvertieren, die die OpenMP verwendet parallel und für Richtlinien zur Verwendung von Parallelität Runtime concurrency::parallel_for Algorithmus.

Beispiel

In diesem Beispiel wird die Anzahl der Primzahlen in einem Array von Zufallswerten sowohl mit OpenMP als auch mit der Concurrency Runtime berechnet.

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

Folgende Ergebnisse werden zurückgegeben:

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

Der parallel_for-Algorithmus und OpenMP 3.0 lassen als Indextyp einen ganzzahligen Typ mit Vorzeichen und einen ganzzahligen Typ ohne Vorzeichen zu.Der parallel_for-Algorithmus stellt außerdem sicher, dass der angegebene Bereich bei einem Typ mit Vorzeichen keinen Überlauf verursacht.Version 2.0 und 2.5 von OpenMP lassen nur ganzzahlige Indextypen mit Vorzeichen zu.In OpenMP wird außerdem der Indexbereich nicht überprüft.

Verwendet die Version dieses Beispiels, das die Parallelität Runtime verwendet auch eine concurrency::combinable Objekt anstelle der atomar Richtlinie, um den Wert des Indikators zu erhöhen, ohne Synchronisierung.

Weitere Informationen zu parallel_for und anderen parallelen Algorithmen finden Sie unter Parallele Algorithmen.Weitere Informationen zur combinable-Klasse finden Sie unter Parallele Container und Objekte.

Dieses Beispiel unterscheidet sich vom vorherigen Beispiel darin, dass statt eines systemeigenen Arrays ein std::array-Objekt verwendet wird.Da in OpenMP, Version 2.0 und 2.5, ganzzahlige Indextypen mit Vorzeichen nur in einem parallelfor-Konstrukt zulässig sind, können Sie für den parallelen Zugriff auf die Elemente eines STL (Standard Template Library)-Containers keine Iteratoren verwenden.Parallele Muster Library (PPL) stellt die concurrency::parallel_for_each -Algorithmus, der Aufgabe parallel auf eine iterative Container wie z. B. von der STL.Er verwendet die gleiche Partitionierungslogik wie der parallel_for-Algorithmus.Der parallel_for_each-Algorithmus ähnelt dem std::for_each-Algorithmus der STL, mit dem Unterschied, dass der parallel_for_each-Algorithmus die Aufgaben gleichzeitig ausführt.

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

Kompilieren des Codes

Kopieren Sie den Beispielcode und fügen Sie ihn in ein Visual Studio Projekt, oder fügen Sie ihn in eine Datei mit dem Namen Concrt-Omp-Count-primes.cpp und führen Sie den folgenden Befehl in ein Visual Studio-Eingabeaufforderungsfenster.

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

Siehe auch

Konzepte

Migrieren von OpenMP zur Concurrency Runtime

Parallele Algorithmen

Parallele Container und Objekte