He estado probando el rendimiento de System.Threading.Parallel frente a Threading y me sorprende ver que Parallel tarda más tiempo en terminar las tareas que en el enhebrado. Estoy seguro de que se debe a mi conocimiento limitado de Parallel, que acabo de comenzar a leer.C# Paralelo vs. Ejecución del código con subprocesos
Pensé que voy a compartir algunos fragmentos y si alguien puede señalarme, el código paralelo se ejecuta más lento que el código enhebrado. También intenté ejecutar la misma comparación para encontrar números primos y encontré el código paralelo que termina mucho más tarde que el código enhebrado.
public class ThreadFactory
{
int workersCount;
private List<Thread> threads = new List<Thread>();
public ThreadFactory(int threadCount, int workCount, Action<int, int, string> action)
{
workersCount = threadCount;
int totalWorkLoad = workCount;
int workLoad = totalWorkLoad/workersCount;
int extraLoad = totalWorkLoad % workersCount;
for (int i = 0; i < workersCount; i++)
{
int min, max;
if (i < (workersCount - 1))
{
min = (i * workLoad);
max = ((i * workLoad) + workLoad - 1);
}
else
{
min = (i * workLoad);
max = (i * workLoad) + (workLoad - 1 + extraLoad);
}
string name = "Working Thread#" + i;
Thread worker = new Thread(() => { action(min, max, name); });
worker.Name = name;
threads.Add(worker);
}
}
public void StartWorking()
{
foreach (Thread thread in threads)
{
thread.Start();
}
foreach (Thread thread in threads)
{
thread.Join();
}
}
}
Este es el programa:
Stopwatch watch = new Stopwatch();
watch.Start();
int path = 1;
List<int> numbers = new List<int>(Enumerable.Range(0, 10000));
if (path == 1)
{
Parallel.ForEach(numbers, x =>
{
Console.WriteLine(x);
Thread.Sleep(1);
});
}
else
{
ThreadFactory workers = new ThreadFactory(10, numbers.Count, (min, max, text) => {
for (int i = min; i <= max; i++)
{
Console.WriteLine(numbers[i]);
Thread.Sleep(1);
}
});
workers.StartWorking();
}
watch.Stop();
Console.WriteLine(watch.Elapsed.TotalSeconds.ToString());
Console.ReadLine();
Actualización:
Tomando en consideración Bloqueo: He probado el siguiente fragmento. De nuevo los mismos resultados, Parallel parece terminar mucho más lento.
ruta = 1; cieling = 10000000;
List<int> numbers = new List<int>();
if (path == 1)
{
Parallel.For(0, cieling, x =>
{
lock (numbers)
{
numbers.Add(x);
}
});
}
else
{
ThreadFactory workers = new ThreadFactory(10, cieling, (min, max, text) =>
{
for (int i = min; i <= max; i++)
{
lock (numbers)
{
numbers.Add(i);
}
}
});
workers.StartWorking();
}
Actualización 2: Sólo una rápida actualización que mi máquina tiene procesador de cuatro núcleos. Entonces Parallel tiene 4 núcleos disponibles.
No debe bloquear el ForEach, lo hace internamente. Pero el uso de un ReaderWriterLockSlim lo volverá a hacer rápidamente;) –
Establezca ThreadFactory en 2 hilos y configure la concurrencia máxima en el Paralelo.Para 2, elimine Console.WriteLine y haga algo más apropiado. Ahora, ¿cómo se comparan? Prueba 3 y 3; 4 y 4; ... En algún momento, Parallel.ForEach decidirá que tiene asignados suficientes hilos y asignará menos del máximo que usted le indique, pero al menos hasta ese punto estará comparando los tiempos usando el * mismo * número de hilos. –
@Hightechrider: Bueno, en términos de arrojar carga de trabajo real, como mencioné en mi pregunta, probé esto contra encontrar números primos también, que bastante procesador intensivo, muestra el 100% de actividad en todo momento, y descubrí que ThreadFactory funciona más rápido. Pruébelo y vea ... Incluso traté de configurar el conteo de hilos a 2,3, etc. Los mismos resultados. – ace