¿Por qué este código paralelo es más lento que su versión no paralela similar?

Tengo el siguiente código (copiado aquí desde LINQPad). Obviamente parece que no entiendo cómo funciona TPL o si el código es basura, ¿por qué la versión paralela se ejecuta más lentamente que su contraparte no paralela?

for (int i = 0; i < 100; i++) { ParallelOptions ops = new ParallelOptions(); ops.MaxDegreeOfParallelism = Environment.ProcessorCount; var watch = Stopwatch.StartNew(); Parallel.ForEach(Enumerable.Range(1, 10000000), ops, x => { int y = x + 1; }); watch.Stop(); Console.WriteLine("Parallel: {0}", watch.Elapsed.TotalSeconds); watch = Stopwatch.StartNew(); foreach (var x in Enumerable.Range(1, 10000000)) { int y = x + 1; } watch.Stop(); Console.WriteLine("Non-parallel: {0}\n", watch.Elapsed.TotalSeconds); } 

Primeros 10 resultados:

Paralelo: 0.1991644 No paralelo: 0.0466178

Paralela: 0.1723428 No paralela: 0.0447134

Paralelo: 0.1141791 No paralelo: 0.0444557

Paralelo: 0.1758878 No paralelo: 0.0444636

Paralelo: 0.1687637 No paralelo: 0.0444338

Paralelo: 0.1677679 No paralelo: 0.0445771

Paralelo: 0.1191462 No paralelo: 0.0446116

Paralela: 0.1702483 No paralela: 0.0454863

Paralelo: 0.1143605 No paralelo: 0.0451731

Paralelo: 0.2155218 No paralelo: 0.0450392

Bueno, la mejor respuesta que puede obtener es ejecutar una herramienta de perfilador y medir lo que está sucediendo con su código. Pero mi conjetura es que su código paralelo es más lento porque su código es tan simple que iniciar subprocesos y cambiar entre ellos sum tanto costo que cualquier ventaja en la velocidad de cálculo es insignificante.

Pero intente realizar algunos cálculos sustanciales y finalmente tendrá la ventaja de la ejecución paralela. Su código es demasiado simple. Las CPU modernas no deben cargarse de esta manera.

Como no puedo agregar esto como un comentario, estoy agregando otra respuesta para publicar el código modificado. Lo que @ixSci dijo en su respuesta parece ser correcto. Estaba realizando una operación trivial en el cuerpo del código paralelo que se ejecutaba realmente rápido, pero la lentitud se debió al hecho de que se invirtió mucho tiempo en el cambio de contexto entre subprocesos. Cuando cambié el código de suspensión durante algún tiempo en lugar de boost el valor de int en 1, el código paralelo fue aproximadamente 4 (no. Núcleos en mi CPU) veces más rápido que la versión no paralela.

 for (int i = 0; i < 100; i++) { ParallelOptions ops = new ParallelOptions(); ops.MaxDegreeOfParallelism = Environment.ProcessorCount; var partitioner = Partitioner.Create(Enumerable.Range(1, 5000)); var watch = Stopwatch.StartNew(); Parallel.ForEach(partitioner, ops, x => { Thread.Sleep(1); }); watch.Stop(); Console.WriteLine("Parallel: {0}", watch.Elapsed.TotalSeconds); watch = Stopwatch.StartNew(); foreach (var x in Enumerable.Range(1, 5000)) { Thread.Sleep(1); } watch.Stop(); Console.WriteLine("Non-parallel: {0}\n", watch.Elapsed.TotalSeconds); } 

Primeros 10 resultados:

Paralelo: 1.2887589 No paralelo: 5.0020569

Paralelo: 1.277047 No paralelo: 5.0011116

Paralelo: 1.2790631 No paralelo: 5.0001498

Paralelo: 1.2770644 No paralelo: 5.0052016

Paralelo: 1.2770013 No paralelo: 5.0021479

Paralelo: 1.2770031 No paralelo: 5.0001927

Paralelo: 1.2799937 No paralelo: 5.0062141

Paralela: 1.2819909 No paralela: 5.0171945

Paralelo: 1.2780496 No paralelo: 5.0071667

Paralelo: 1.2821714 No paralelo: 5.0082108

Paralelo: 1.2777875 No paralelo: 5.0152099

    Intereting Posts