Compartilhar via


Como: Converter uma paralela OpenMP para Loop usar o Runtime de simultaneidade

Este exemplo demonstra como converter um loop básico que usa o OpenMP paralela e para diretivas para usar o Runtime de simultaneidade Concurrency::parallel_for algoritmo.

Exemplo

Este exemplo usa o OpenMP e o Runtime de simultaneidade para calcular a contagem dos números primos de uma matriz de valores aleatórios.

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

O exemplo produz a seguinte saída.

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

O parallel_for algoritmo e OpenMP 3.0 permitem o tipo de índice ser um tipo integral é assinado ou um tipo integral não assinados. O parallel_for algoritmo também certifica-se de que o intervalo especificado não estourar um tipo assinado. OpenMP versões 2.0 e 2.5 permitem somente os tipos de índice de integral assinado. O OpenMP também não valida o intervalo de índice.

A versão desse exemplo que usa o Runtime de simultaneidade também usa um Concurrency::combinable de objeto no lugar da atomic diretiva para incrementar o valor de contador, sem a necessidade de sincronização.

Para obter mais informações sobre parallel_for e outros algoritmos paralelos, consulte Algoritmos paralelos. For more information about the combinable class, see Paralelo recipientes e objetos.

Este exemplo modifica a uma anterior para atuar em um std::array de objeto em vez de em um array nativo. Porque o OpenMP versões 2.0 e 2.5 permitem para os tipos de índice integral somente em um parallel for a construção, você não pode usar iteradores para acessar os elementos de um recipiente de biblioteca STL (Standard Template) em paralelo. O paralela padrões PPL (biblioteca) fornece a Concurrency::parallel_for_each algoritmo, que executa tarefas, em paralelo, em um contêiner de iterativo, como aqueles fornecidos pela STL. Ele usa a mesma lógica de particionamento que o parallel_for algoritmo usa. O parallel_for_each algoritmo semelhante a STL std::for_each o algoritmo, exceto que o parallel_for_each algoritmo executa as tarefas simultaneamente.

// 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(a.begin(), a.end(), [&counts](int n) 
   {
      if (is_prime(n)) {
         counts.local()++;
      }
   });

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

Compilando o código

Copie o código de exemplo e colá-lo em um Visual Studio do projeto, ou colá-lo em um arquivo que é chamado concrt-omp contagem primes.cpp e, em seguida, execute o seguinte comando um Visual Studio 2010 janela do Prompt de comando.

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

Consulte também

Conceitos

Algoritmos paralelos

Paralelo recipientes e objetos

Outros recursos

Migrando do OpenMP para o Runtime de simultaneidade