Procedimiento para escribir un bucle parallel_for_each
En este ejemplo se muestra cómo usar el algoritmo concurrency::parallel_for_each
para calcular el recuento de números primos en un objeto std::array
en paralelo.
Ejemplo
En el siguiente ejemplo se calcula dos veces el recuento de números primos en una matriz. En el ejemplo se usa primero el algoritmo std::for_each
para calcular el recuento en serie. A continuación, en el ejemplo se usa el algoritmo parallel_for_each
para realizar la misma tarea en paralelo. También se imprime en la consola el tiempo necesario para realizar ambos cálculos.
// 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;
// Returns the number of milliseconds that it takes to call the passed in function.
template <class Function>
__int64 time_call(Function&& f)
{
__int64 begin = GetTickCount();
f();
return GetTickCount() - begin;
}
// Determines whether the input is a prime.
bool is_prime(int n)
{
if (n < 2)
{
return false;
}
for (int i = 2; i < int(std::sqrt(n)) + 1; ++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++;
});
// Use the for_each algorithm to count, serially, the number
// of prime numbers in the array.
LONG prime_count = 0L;
__int64 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, in parallel, the number
// of prime numbers in the array.
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;
}
La siguiente salida de ejemplo se corresponde a un equipo con cuatro núcleos.
serial version:
found 17984 prime numbers
took 125 ms
parallel version:
found 17984 prime numbers
took 63 ms
Compilar el código
Para compilar el código, cópielo y péguelo en un proyecto de Visual Studio, o en un archivo denominado parallel-count-primes.cpp
. Después, ejecute el comando siguiente en una ventana del símbolo del sistema de Visual Studio.
cl.exe /EHsc parallel-count-primes.cpp
Programación sólida
La expresión lambda que el ejemplo pasa al algoritmo parallel_for_each
usa la función InterlockedIncrement
para permitir a las iteraciones paralelas del bucle incrementar el contador simultáneamente. Si usa funciones como InterlockedIncrement
para sincronizar el acceso a los recursos compartidos, pueden presentarse cuellos de botella de rendimiento en el código. Puede usar un mecanismo de sincronización sin bloqueos, por ejemplo, la clase concurrency::combinable
, para eliminar el acceso simultáneo a los recursos compartidos. Para obtener un ejemplo en el que se usa la clase combinable
de esta manera, vea Procedimiento para usar combinable para mejorar el rendimiento.
Consulte también
Comentarios
https://aka.ms/ContentUserFeedback.
Proximamente: Ao longo de 2024, retiraremos gradualmente GitHub Issues como mecanismo de comentarios sobre o contido e substituirémolo por un novo sistema de comentarios. Para obter máis información, consulte:Enviar e ver os comentarios