2009-11-28 4 views
6

Il ne semble pas faire de squat pour le programme de test suivant. Est-ce parce que je teste avec une petite liste?Comment AsParallel fonctionne-t-il exactement?

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; 
} 

Les deux versions prennent 4 secondes à s'exécuter.

+2

Comment avez-vous obtenu Upto, une méthode d'extension? – thewpfguy

Répondre

23

La bibliothèque parallèle de tâches se soucie du type statique de la séquence. Il devrait être IParallelEnumerable<T> pour les opérations devant être traitées par le TPL. Vous ramenez la collection à IEnumerable<T> lorsque vous appelez Test. Par conséquent, le compilateur va résoudre .Where appel sur la séquence à la méthode d'extension System.Linq.Enumerable.Where au lieu de la version parallèle fournie par le TPL.

1

Comme Parallel fonctionne en mettant vos trucs dans le ThreadPool. Aussi, combien de noyaux avez-vous? Si vous travaillez sur un seul ordinateur central, il vous faudra environ 4 secondes pour l'exécuter.

5

(Mise à jour pour .NET4 car cette question se classe assez élevé dans une recherche Google pour AsParallel())

Juste quelques changements permettra à votre exemple de travailler comme je l'imagine que vous attendiez.

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

Votre exemple fonctionnerait si vous avez ajouté une surcharge de fonction avec une signature qui prend 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"); 
    } 

Sinon, vous pouvez utiliser la syntaxe 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"); 
    } 

Espérons que cela aide quelqu'un!