2012-05-26 15 views
6

He intentado un ejemplo muy mínimo:¿Cómo se ejecuta el bucle secuencial más rápido que el bucle paralelo en C#?

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Threading; 
using System.Collections.Concurrent; 
using System.Diagnostics; 

namespace TPLExample { 
    class Program { 
     static void Main(string[] args) { 
      int[] dataItems = new int[100]; 
      double[] resultItems = new double[100]; 

      for (int i = 0; i < dataItems.Length; ++i) { 
       dataItems[i] = i; 
      } 

      Stopwatch stopwatch = new Stopwatch(); 

      stopwatch.Reset(); 
      stopwatch.Start(); 
      Parallel.For(0, dataItems.Length, (index) => { 
       resultItems[index] = Math.Pow(dataItems[index], 2); 
      }); 
      stopwatch.Stop(); 
      Console.WriteLine("TPL Time elapsed: {0}", stopwatch.Elapsed); 

      stopwatch.Reset(); 
      stopwatch.Start(); 
      for (int i = 0; i < dataItems.Length; ++i) { 
       resultItems[i] = Math.Pow(dataItems[i], 2); 
      } 
      stopwatch.Stop(); 
      Console.WriteLine("Sequential Time elapsed: {0}", stopwatch.Elapsed); 

      WaitForEnterKey(); 
     } 

     public static void WaitForEnterKey() { 
      Console.WriteLine("Press enter to finish"); 
      Console.ReadLine(); 
     } 

     public static void PrintMessage() { 
      Console.WriteLine("Message printed"); 
     } 
    } 
} 

La salida fue:

TPL Time elapsed: 00:00:00.0010670 
Sequential Time elapsed: 00:00:00.0000178 
Press enter to finish 

El bucle secuencial es mucho más rápido que la TPL! ¿Cómo es esto posible? Según entiendo, el cálculo dentro del Parallel.For se ejecutará en paralelo, entonces ¿debe ser más rápido?

+1

probarlo por un millón de artículos con decir 10 hilos. – Josnidhin

Respuesta

10

En pocas palabras: por solo iterar más de cien elementos y realizar una pequeña operación matemática, generar nuevos hilos y esperar que se completen produce más sobrecarga que el simple hecho de ejecutarlo.

Según mi entender, el cálculo dentro de Parallel.For se ejecutará en paralelo, entonces ¿debe ser más rápido?

Como suele ocurrir cuando las personas hacen afirmaciones generales sobre el rendimiento de la computadora, hay muchas más variables en juego aquí, y realmente no se puede hacer esa suposición. Por ejemplo, dentro de su bucle for, no está haciendo más que Math.Pow, que el procesador puede realizar muy rápidamente. Si se tratara de una operación intensiva de E/S, que requiere que cada hilo espere mucho tiempo, o incluso si se tratara de una serie de operaciones intensivas en el procesador, obtendría más del procesamiento en paralelo (suponiendo que tiene un procesador de subprocesos múltiples) . Pero tal como está, la sobrecarga de crear y sincronizar estos hilos es mucho mayor que cualquier ventaja que el paralelismo pueda darte.

+2

No es el número de iteraciones lo que más preocupa (y el TPL no generará nuevos hilos, sino que los programará en el 'ThreadPool', para ser exactos). Es el costo de la operación en sí, que en este caso es trivial. –

+0

Ah, eso tiene sentido. Gracias. – Chan

+0

@ Adamrobinson: Gracias por mantener las cosas precisas. :-) – StriplingWarrior

10

El procesamiento de bucle paralelo es útil cuando la operación realizada dentro del bucle es relativamente costosa. Todo lo que estás haciendo en tu ejemplo es calcular un exponente, que es trivial. La sobrecarga de multihilo supera con creces las ganancias que obtendrás en este caso.

1

La sobrecarga de la paralelización es mucho mayor que simplemente ejecutar Math.Pow 100 veces de forma secuencial. Los otros han dicho esto.

Más importante, sin embargo, el acceso a la memoria es trivial en la versión secuencial, pero con la versión paralela, los hilos tienen que compartir la memoria (resultItems) y ese tipo de cosas se realmente matar, incluso si tiene una millones de artículos.

Ver página 44 del presente excelente Microsoft libro blanco sobre la programación paralela: http://www.microsoft.com/en-us/download/details.aspx?id=19222. Aquí hay un artículo de la revista MSDN sobre el tema: http://msdn.microsoft.com/en-us/magazine/cc872851.aspx

2

Este ejemplo de código es una prueba práctica muy buena respuestas anteriores.

He simulado el funcionamiento intensivo del procesador simplemente bloqueando el hilo por Thead.Sleep.

La salida fue:

  • secuencial Loop - 00: 00: 09,9995500
  • paralelo Loop - 00:00:03.0347901

_

class Program 
{ 
    static void Main(string[] args) 
    { 
     const int a = 10; 

     Stopwatch sw = new Stopwatch(); 
     sw.Start(); 

     //for (long i = 0; i < a; i++) 
     //{ 
     // Thread.Sleep(1000); 
     //} 

     Parallel.For(0, a, i => 
     { 
      Thread.Sleep(1000); 
     }); 

     sw.Stop(); 

     Console.WriteLine(sw.Elapsed); 

     Console.ReadLine(); 
    } 
} 
Cuestiones relacionadas