c# - tpl - vb net parallel programming examples




Parallel.ForEach vs Task.Factory.StartNew (3)

En mi opinión, el escenario más realista es cuando las tareas tienen una operación pesada que completar. El enfoque de Shivprasad se centra más en la creación de objetos / asignación de memoria que en la informática en sí. Hice una investigación llamando al siguiente método:

public static double SumRootN(int root)
{
    double result = 0;
    for (int i = 1; i < 10000000; i++)
        {
            result += Math.Exp(Math.Log(i) / root);
        }
        return result; 
}

La ejecución de este método toma alrededor de 0.5 seg.

Lo llamé 200 veces usando paralelo:

Parallel.For(0, 200, (int i) =>
{
    SumRootN(10);
});

Luego lo llamé 200 veces usando la manera antigua:

List<Task> tasks = new List<Task>() ;
for (int i = 0; i < loopCounter; i++)
{
    Task t = new Task(() => SumRootN(10));
    t.Start();
    tasks.Add(t);
}

Task.WaitAll(tasks.ToArray()); 

Primer caso completado en 26656ms, el segundo en 24478ms. Lo repetí muchas veces. Cada vez que el segundo enfoque es marginalmente más rápido.

¿Cuál es la diferencia entre los siguientes fragmentos de código? ¿No estarán ambos usando hilos de hilos?

Por ejemplo, si quiero llamar a una función para cada elemento de una colección,

Parallel.ForEach<Item>(items, item => DoSomething(item));

vs

foreach(var item in items)
{
  Task.Factory.StartNew(() => DoSomething(item));
}

Hice un pequeño experimento de ejecutar un método "1000000000" veces con "Parallel.For" y uno con objetos "Task".

Medí el tiempo del procesador y encontré el paralelo más eficiente. Parallel.For divide su tarea en pequeños elementos de trabajo y los ejecuta en todos los núcleos de forma paralela de una manera óptima. Mientras se crean muchos objetos de tareas (FYI TPL utilizará la agrupación de subprocesos internamente) moverá cada ejecución en cada tarea, lo que creará más tensión en el cuadro, lo que se evidencia en el experimento a continuación.

También he creado un pequeño video que explica el TPL básico y también demostró cómo Parallel.For utiliza su núcleo de manera más eficiente http://www.youtube.com/watch?v=No7QqSc5cl8 en comparación con las tareas y subprocesos normales.

Experimento 1

Parallel.For(0, 1000000000, x => Method1());

Experimento 2

for (int i = 0; i < 1000000000; i++)
{
    Task o = new Task(Method1);
    o.Start();
}


Parallel.ForEach optimizará (puede que ni siquiera inicie nuevos subprocesos) y se bloqueará hasta que finalice el ciclo, y Task.Factory creará explícitamente una nueva instancia de tarea para cada elemento y regresará antes de que finalice (tareas asíncronas). Parallel.Foreach es mucho más eficiente.





parallel-extensions