2010-09-15 5 views
7

J'ai récemment déménagé à C# .net 4.Quand utiliser Parallel.For?

J'aime Parallel.For, mais je ne sais pas quand l'utiliser et quand ne pas le faire. Je sais que lorsque la commande n'est pas importante pour moi - je vais l'utiliser.

Mais y a-t-il des tests concernant le temps de travail avec Parallels? C'est-à-dire, si ma boucle ne fonctionne que 10 fois (et qu'elle exécute très peu de logique) - devrais-je éviter Parallels? Y a-t-il des règles de pouce?

+0

Voici un très bon ebook gratuit de Microsoft qui couvre ce sujet " [Patterns pour la programmation parallèle: Comprendre et appliquer des modèles parallèles avec le .NET Framework 4] (https://www.microsoft.com/en-us/download/details.aspx?id=19222) " –

Répondre

4

J'éviterais d'utiliser Parallel.For sauf si les performances sont un problème.

L'écriture de code qui s'exécute simultanément est en général plus difficile que l'écriture d'un seul code. De plus, si vous faites une erreur en raison d'un problème de simultanéité, il peut être difficile de le déboguer. Par exemple, le bug peut survenir seulement parfois et ne pas être facilement reproductible. À moins que vous ayez un besoin spécifique d'augmentation des performances, je vous suggère de rester simple et d'utiliser une boucle ordinaire sur un seul thread.

+0

Je suis d'accord - don ' t juste l'utiliser parce qu'il est là, à la place , essayez de résoudre un problème réel avec. En outre, profilage est votre ami;) –

+0

Je pense que "la performance est un problème" était implicite ici. –

+0

Je suis d'accord avec Mark. Utilisez les ressources les moins possibles pour un travail. – Josh

0

Citation de SQLite FAQ: 'Threads are evil. Les éviter '

La parallélisation est utile pour les performances. L'optimisation des performances des applications est l'une des choses les plus intuitives dans la conception de logiciels, et doit être effectuée avec le plus grand soin, en utilisant les bons outils de mesure, ou tout simplement drôle. Certains pourraient optimiser le code d'interface utilisateur pour répondre en une microseconde au lieu de millisecondes, n'ayant clairement aucune valeur et causant beaucoup de dommages.

+0

Une certaine vérité à ce sujet, mais tout à fait trop simple. Voir par exemple http: // stackoverflow.com/questions/3415519/est-il-un-point-à-multithreading/3415563 # 3415563 –

1

La boucle Parallel.For utilise ThreadPool pour exécuter le travail dans une boucle en invoquant un délégué une fois pour chaque itération d'une boucle.

L'idée générale de la façon dont fonctionne Parallel.For peut être présenté comme suit:

public static void MyParallelFor(int inclusiveLowerBound, int exclusiveUpperBound, Action<int> body) 
{ 
    // Get the number of processors, initialize the number of remaining 
    // threads, and set the starting point for the iteration. 
    int numProcs = Environment.ProcessorCount; 
    int remainingWorkItems = numProcs; 
    int nextIteration = inclusiveLowerBound; 
    using (ManualResetEvent mre = new ManualResetEvent(false)) 
    { 
     // Create each of the work items. 
     for (int p = 0; p < numProcs; p++) 
     { 
      ThreadPool.QueueUserWorkItem(delegate 
      { 
       int index; 
       while ((index = Interlocked.Increment(ref nextIteration) - 1) < exclusiveUpperBound) 
        body(index); 

       if (Interlocked.Decrement(ref remainingWorkItems) == 0) 
        mre.Set(); 
      }); 
     } 
     // Wait for all threads to complete. 
     mre.WaitOne(); 
    } 
} 

retourne Parallel.For type de valeur ParallelLoopResult, qui contient des détails sur la boucle terminée. L'un de ses surcharges est la suivante:

public static ParallelLoopResult For(int fromInclusive, int toExclusive, Action<int> body); 

Il est important de réaliser que l'exécution parallèle n'est pas toujours plus rapide que l'exécution en série. Pour décider d'utiliser parallèlement ou non, vous devez estimer la charge de travail qui va faire par itération d'une boucle. Si le travail réel effectué par la boucle est faible par rapport au coût de la synchronisation des threads, il est préférable d'utiliser une boucle ordinaire.

Ceci est un exemple en série pour des performances en boucle est plus rapide que parallèle:

static void Main(string[] args) 
{ 
    Action<int> action = new Action<int>(SimpleMethod); 

    // ordinary For loop performance estimation 
    var sw = Stopwatch.StartNew(); 

    for(int i = 0; i < 1000; i++) 
     action(i); 

    Console.WriteLine("{0} sec.", sw.Elapsed.TotalSeconds); 

    // parallel For loop performance estimation 
    sw = Stopwatch.StartNew(); 

    Parallel.For(0, 1000, action); 

    Console.WriteLine("{0} sec.", sw.Elapsed.TotalSeconds); 
} 

static void SimpleMethod(int index) 
{ 
    int d = 1; 
    int result = index/d; 
} 

Sortie:

0.0001963 sec. 
0.0346729 sec.