Freigeben über


Gewusst wie: Schreiben einer parallel_for_each-Schleife

In diesem Beispiel wird veranschaulicht, wie mithilfe der concurrency::parallel_for_each Algorithmus zur Berechnung der Anzahl der Primzahlen in einer std::array Objekt parallel.

Beispiel

Im folgenden Beispiel wird die Anzahl von Primzahlen in einem Array zweimal berechnet.Im Beispiel wird zunächst die Anzahl mit dem std::for_each-Algorithmus seriell berechnet.Anschließend wird die gleiche Aufgabe mit dem parallel_for_each-Algorithmus parallel ausgeführt.Das Beispiel gibt außerdem die Zeit, die zum Ausführen beider Berechnungen benötigt wird, in der Konsole aus.

// parallel-count-primes.cpp
// compile with: /EHsc
#include <windows.h>
#include <ppl.h>
#include <iostream>
#include <algorithm>
#include <array>

using namespace concurrency;
using namespace std;

// Calls the provided work function and returns the number of milliseconds 
// that it takes to call that function.
template <class Function>
__int64 time_call(Function&& f)
{
   __int64 begin = GetTickCount();
   f();
   return GetTickCount() - begin;
}

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

int wmain()
{
   // Create an array object that contains 200000 integers.
   array<int, 200000> a;

   // Initialize the array such that a[i] == i.
   int n = 0;
   generate(begin(a), end(a), [&] {
      return n++;
   });

   LONG prime_count;
   __int64 elapsed;

   // Use the for_each algorithm to count the number of prime numbers
   // in the array serially.
   prime_count = 0L;
   elapsed = time_call([&] {
      for_each (begin(a), end(a), [&](int n ) { 
         if (is_prime(n))
            ++prime_count;
      });
   });
   wcout << L"serial version: " << endl
         << L"found " << prime_count << L" prime numbers" << endl
         << L"took " << elapsed << L" ms" << endl << endl;

   // Use the parallel_for_each algorithm to count the number of prime numbers
   // in the array in parallel.
   prime_count = 0L;
   elapsed = time_call([&] {
      parallel_for_each (begin(a), end(a), [&](int n ) { 
         if (is_prime(n))
            InterlockedIncrement(&prime_count);
      });
   });
   wcout << L"parallel version: " << endl
         << L"found " << prime_count << L" prime numbers" << endl
         << L"took " << elapsed << L" ms" << endl << endl;
}

Die folgende Beispielausgabe entspricht einem Ergebnis auf einem Computer mit vier Prozessoren.

serial version:
found 17984 prime numbers
took 6115 ms

parallel version:
found 17984 prime numbers
took 1653 ms

Kompilieren des Codes

Um den Code zu kompilieren, kopieren Sie ihn ein und fügen Sie ihn in einem Projekt Visual Studio oder fügen Sie ihn in eine Datei mit dem Namen Parallel-Count-primes.cpp und führen Sie den folgenden Befehl in ein Visual Studio-Eingabeaufforderungsfenster.

cl.exe /EHsc parallel-count-primes.cpp

Robuste Programmierung

Der Lambda-Ausdruck, der im Beispiel an den parallel_for_each-Algorithmus übergeben wird, aktiviert mithilfe der InterlockedIncrement-Funktion parallele Iterationen der Schleife, um den Zähler gleichzeitig zu inkrementieren.Wenn Sie Funktionen wie z. B. InterlockedIncrement verwenden, um Zugriff auf freigegebene Ressourcen zu synchronisieren, kann es zu Leistungsengpässen im Code kommen.Können Sie einen Lock-free Synchronisierungsmechanismus z. B., die concurrency::combinable -Klasse, um gleichzeitigen Zugriff auf freigegebene Ressourcen zu beseitigen.Ein Beispiel, in dem die combinable-Klasse auf diese Weise verwendet wird, finden Sie unter Gewusst wie: Verbessern der Leistung mithilfe von combinable.

Siehe auch

Referenz

parallel_for_each-Funktion

Konzepte

Parallele Algorithmen