Cómo: Usar la clase combinable para combinar conjuntos

En este tema se muestra cómo usar la clase concurrency::combinable para calcular el conjunto de números primos.

Ejemplo

En el siguiente ejemplo se calcula el conjunto de números primos dos veces. Cada cálculo almacena el resultado en un objeto std::bitset. El ejemplo calcula en primer lugar el conjunto en serie y, a continuación, lo calcula en paralelo. También se imprime en la consola el tiempo necesario para realizar ambos cálculos.

En este ejemplo se usa el algoritmo concurrency::parallel_for y un objeto combinable para generar conjuntos locales de subprocesos. A continuación, se usa el método concurrency::combinable::combine_each para combinar los conjuntos locales de subprocesos en el conjunto final.

// parallel-combine-primes.cpp
// compile with: /EHsc
#include <windows.h>
#include <ppl.h>
#include <bitset>
#include <iostream>

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

const int limit = 40000;

int wmain()
{
   // A set of prime numbers that is computed serially.
   bitset<limit> primes1;

   // A set of prime numbers that is computed in parallel.
   bitset<limit> primes2;

   __int64 elapsed;

   // Compute the set of prime numbers in a serial loop.
   elapsed = time_call([&] 
   {
      for(int i = 0; i < limit; ++i) {
         if (is_prime(i))
            primes1.set(i);
      }
   });
   wcout << L"serial time: " << elapsed << L" ms" << endl << endl;

   // Compute the same set of numbers in parallel.
   elapsed = time_call([&] 
   {
      // Use a parallel_for loop and a combinable object to compute 
      // the set in parallel. 
      // You do not need to synchronize access to the set because the 
      // combinable object provides a separate bitset object to each thread.
      combinable<bitset<limit>> working;
      parallel_for(0, limit, [&](int i) {
         if (is_prime(i))
            working.local().set(i);
      });

      // Merge each thread-local computation into the final result.
      working.combine_each([&](bitset<limit>& local) {
         primes2 |= local;
      });
   });
   wcout << L"parallel time: " << elapsed << L" ms" << endl << endl;
}

La siguiente salida de ejemplo corresponde a un equipo con cuatro procesadores.

serial time: 312 ms

parallel time: 78 ms

Compilar el código

Copie el código de ejemplo y péguelo en un proyecto de Visual Studio o en un archivo denominado parallel-combine-primes.cpp y, después, ejecute el siguiente comando en una ventana del símbolo del sistema de Visual Studio.

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

Consulte también

Contenedores y objetos paralelos
combinable (clase)
combinable::combine_each (Método)