Delen via


Procedure: Een OpenMP-parallelle for-lus converteren om de Gelijktijdigheidsruntime te gebruiken

In dit voorbeeld wordt gedemonstreerd hoe u een eenvoudige lus kunt omzetten die gebruikmaakt van OpenMP parallel en for instructies naar een toepassing van de Concurrency Runtime concurrency::parallel_for algoritme.

Voorbeeld: aantal priemgetallen

In dit voorbeeld worden zowel OpenMP als de Gelijktijdigheidsruntime gebruikt om het aantal priemgetallen in een matrix met willekeurige waarden te berekenen.

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

In dit voorbeeld wordt de volgende uitvoer geproduceerd.

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

Met parallel_for het algoritme en OpenMP 3.0 kan het indextype een ondertekend integraal type of een niet-ondertekend integraaltype zijn. Het parallel_for algoritme zorgt er ook voor dat het opgegeven bereik een ondertekend type niet overloopt. OpenMP-versies 2.0 en 2.5 staan alleen ondertekende integrale indextypen toe. OpenMP valideert ook het indexbereik niet.

De versie van dit voorbeeld die gebruikmaakt van de Gelijktijdigheidsruntime maakt ook gebruik van een gelijktijdigheid::combineerbaar object in plaats van de atomische instructie om de tellerwaarde te verhogen zonder synchronisatie te vereisen.

Zie parallel_for algoritmen voor meer informatie over en andere parallelle algoritmen. Zie combinable voor meer informatie over de klasse.

Voorbeeld: std::array gebruiken

In dit voorbeeld wordt de vorige gewijzigd om te reageren op een object std::array in plaats van op een systeemeigen matrix. Omdat OpenMP-versies 2.0 en 2.5 alleen ondertekende integrale indextypen in een parallel_for constructie toestaan, kunt u iterators niet gebruiken om parallel toegang te krijgen tot de elementen van een C++ Standard Library-container. De Parallel Patterns Library (PPL) biedt de concurrency::parallel_for_each-algoritme, waarmee taken parallel worden uitgevoerd op een container voor iteratie, zoals die wordt geleverd door de C++-standaardbibliotheek. Het maakt gebruik van dezelfde partitioneringslogica die door het parallel_for algoritme wordt gebruikt. Het parallel_for_each algoritme lijkt op het C++- standaardbibliotheek-std::for_each-algoritme , behalve dat het parallel_for_each algoritme de taken gelijktijdig uitvoert.

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

De code compileren

Kopieer de voorbeeldcode en plak deze in een Visual Studio-project, of plak deze in een bestand met de naam concrt-omp-count-primes.cpp en voer vervolgens de volgende opdracht uit in een Visual Studio-opdrachtpromptvenster.

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

Zie ook

Migreren van OpenMP naar de Gelijktijdigheidsruntime
Parallelle algoritmen
parallelle containers en objecten