2009-11-28 9 views
6

No parece hacer sentadillas para el siguiente programa de prueba. ¿Esto es porque estoy probando con una pequeña lista?¿Cómo funciona exactamente AsParallel?

static void Main(string[] args) 
{ 
    List<int> list = 0.UpTo(4); 

    Test(list.AsParallel()); 
    Test(list); 
} 

private static void Test(IEnumerable<int> input) 
{ 
    var timer = new Stopwatch(); 
    timer.Start(); 
    var size = input.Count(); 
    if (input.Where(IsOdd).Count() != size/2) 
     throw new Exception("Failed to count the odds"); 

    timer.Stop(); 
    Console.WriteLine("Tested " + size + " numbers in " + timer.Elapsed.TotalSeconds + " seconds"); 
} 

private static bool IsOdd(int n) 
{ 
    Thread.Sleep(1000); 
    return n%2 == 1; 
} 

Ambas versiones tardan 4 segundos en ejecutarse.

+2

¿Cómo obtuviste Upto, un método de extensión? – thewpfguy

Respuesta

23

Tarea paralela Biblioteca se preocupa por el tipo estático de la secuencia. Debe ser IParallelEnumerable<T> para que las operaciones sean manejadas por TPL. Está lanzando la colección al IEnumerable<T> cuando llama al Test. Por lo tanto, el compilador resolverá la llamada .Where en la secuencia al método de extensión System.Linq.Enumerable.Where en lugar de la versión paralela proporcionada por el TPL.

1

Como Parallel funciona poniendo sus cosas en el ThreadPool. Además, ¿cuántos núcleos tienes? Si está trabajando en una sola máquina central que aún tardará aproximadamente 4 segundos en ejecutarse.

5

(Actualización de .NET4 ya que esta cuestión ocupa bastante alto en una búsqueda en Google de AsParallel())

sólo unos pocos cambios le permitirá a su ejemplo funcione como imagino que esperaba.

Cambio List<int> list = 0.UpTo(4);-var list = Enumerable.Range(0, 4);

Tu ejemplo podría funcionar si se ha añadido una sobrecarga de la función con una firma que tiene un ParallelQuery ...

private static void Test(ParallelQuery<int> input) 
    { 
     var timer = new Stopwatch(); 
     timer.Start(); 

     int size = input.Count(); 
     if (input.Where(IsOdd).Count() != size/2) 
     { 
      throw new Exception("Failed to count the odds"); 
     } 
     timer.Stop(); 

     Console.WriteLine("Tested " + size + " numbers in " + timer.Elapsed.TotalSeconds + " seconds"); 
    } 

Como alternativa, puede utilizar la sintaxis de LINQ ....

private static void Test(ParallelQuery<int> list) 
    { 
     var timer = Stopwatch.StartNew(); 

     if ((from n in list.AsParallel() 
      where IsOdd(n) 
      select n).Count() != (list.Count()/2)) 
     { 
      throw new Exception("Failed to count the odds"); 
     } 

     Console.WriteLine("Tested " + list.Count() + " numbers in " + timer.Elapsed.TotalSeconds + " seconds"); 
    } 

Espero que esto ayude a alguien!

Cuestiones relacionadas