216 votes

Comment utiliser la boucle Parallel.ForEach au lieu de la boucle Foreach classique ? (Informations sur Parallel.ForEach)

Je suis un peu confus à propos Parallel.ForEach .
Qu'est-ce que Parallel.ForEach et que fait-il exactement ?
Veuillez ne pas faire référence à un lien MSDN.

Voici un exemple simple :

string[] lines = File.ReadAllLines(txtProxyListPath.Text);
List<string> list_lines = new List<string>(lines);

foreach (string line in list_lines)
{
    //My Stuff
}

Comment réécrire cet exemple avec Parallel.ForEach ?

0 votes

On a peut-être répondu à cette question ici stackoverflow.com/questions/3789998/

2 votes

@UjjwalManandhar C'est en fait assez différent, puisque la question porte sur la différence entre le Parallel et en utilisant PLINQ.

20 votes

D'autres ont répondu comment vous pouvez réécrire. Alors, que fait-il ? Il effectue une "action" sur chaque élément de la collection, tout comme une action normale foreach . La différence est que la version parallèle peut effectuer plusieurs "actions" en même temps. Dans la plupart des cas (en fonction de l'ordinateur qui exécute le code, de son niveau d'activité et d'autres facteurs), elle sera plus rapide, et c'est l'avantage le plus important. Notez que lorsque vous le faites en parallèle, vous ne pouvez pas savoir dans quelle commander les articles sont traités. Avec un habituel (série) foreach vous avez la garantie que lines[0] vient en premier, puis lines[1] et ainsi de suite.

318voto

Jignesh.Raj Points 2258

Boucle Foreach :

  • Les itérations se déroulent séquentiellement, une par une.
  • La boucle foreach est exécutée à partir d'un seul Thread.
  • La boucle foreach est définie dans tous les frameworks de .NET.
  • L'exécution est plus lente

Parallèle.ForEach :

  • L'exécution se fait de manière parallèle.
  • Parallel.ForEach utilise plusieurs Threads.
  • Parallel.ForEach est défini dans les frameworks .Net 4.0 et plus.
  • L'exécution est plus rapide3

L'exemple suivant démontre clairement la différence entre la boucle foreach traditionnelle et la boucle

Exemple de Parallel.ForEach() .

 using System;
    using System.Diagnostics;
    using System.Threading;
    using System.Threading.Tasks;
    namespace ParallelForEachExample
    {
        class Program
        {
            static void Main()
            {
                string[] colors = {
                                      "1. Red",
                                      "2. Green",
                                      "3. Blue",
                                      "4. Yellow",
                                      "5. White",
                                      "6. Black",
                                      "7. Violet",
                                      "8. Brown",
                                      "9. Orange",
                                      "10. Pink"
                                  };
                Console.WriteLine("Traditional foreach loop\n");
                //start the stopwatch for "for" loop
                var sw = Stopwatch.StartNew();
                foreach (string color in colors)
                {
                    Console.WriteLine("{0}, Thread Id= {1}", color, Thread.CurrentThread.ManagedThreadId);
                    Thread.Sleep(10);
                }
                Console.WriteLine("foreach loop execution time = {0} seconds\n", sw.Elapsed.TotalSeconds);
                Console.WriteLine("Using Parallel.ForEach");
                //start the stopwatch for "Parallel.ForEach"
                 sw = Stopwatch.StartNew();
                Parallel.ForEach(colors, color =>
                {
                    Console.WriteLine("{0}, Thread Id= {1}", color, Thread.CurrentThread.ManagedThreadId);
                    Thread.Sleep(10);
                }
                );
                Console.WriteLine("Parallel.ForEach() execution time = {0} seconds", sw.Elapsed.TotalSeconds);
                Console.Read();
            }
        }
    }

Sortie

Traditional foreach loop
1. Red, Thread Id= 10
2. Green, Thread Id= 10
3. Blue, Thread Id= 10
4. Yellow, Thread Id= 10
5. White, Thread Id= 10
6. Black, Thread Id= 10
7. Violet, Thread Id= 10
8. Brown, Thread Id= 10
9. Orange, Thread Id= 10
10. Pink, Thread Id= 10
foreach loop execution time = 0.1054376 seconds

Utilisation de l'exemple Parallel.ForEach

1. Red, Thread Id= 10
3. Blue, Thread Id= 11
4. Yellow, Thread Id= 11
2. Green, Thread Id= 10
5. White, Thread Id= 12
7. Violet, Thread Id= 14
9. Orange, Thread Id= 13
6. Black, Thread Id= 11
8. Brown, Thread Id= 10
10. Pink, Thread Id= 12
Parallel.ForEach() execution time = 0.055976 seconds

Merci....

67 votes

Je ne suis pas vraiment d'accord avec votre "affirmation" selon laquelle Parallel.ForEach est (toujours) plus rapide. Cela dépend vraiment de la lourdeur de l'opération à l'intérieur de la boucle. Cela peut ou non valoir le surcoût de l'introduction du parallélisme.

0 votes

@Martao dans quels cas n'est-il pas plus rapide ? (Sauf lorsque vous ne disposez que d'un seul cœur/coeur virtuel (thread)).

1 votes

Eh bien, le parallèle pour chacun signifie que des threads séparés sont mis en place pour exécuter le code dans le corps de la boucle. Même si .NET dispose d'un mécanisme efficace pour ce faire, cela représente une surcharge considérable. Ainsi, si vous n'avez qu'une simple opération à effectuer (par exemple, une somme ou une multiplication), le foreach parallèle ne devrait pas être plus rapide.

143voto

L.B Points 54001
string[] lines = File.ReadAllLines(txtProxyListPath.Text);
List<string> list_lines = new List<string>(lines);
Parallel.ForEach(list_lines, line =>
{
    //Your stuff
});

6 votes

Je voulais juste le signaler (plutôt pour l'OP) afin qu'il n'y ait pas de pensée erronée que cela ne fonctionne que sur List<T> ;)

1 votes

Merci pour l'attention et la réponse. J'ai utilisé List<string> dans mes codes parce qu'il est possible de supprimer les éléments en double en utilisant les listes HASH. Avec un tableau ordinaire, nous ne pouvons pas supprimer les doublons facilement :).

129 votes

Je suis confus que cette réponse soit marquée comme la bonne réponse, puisqu'il n'y a aucune explication à la question du message original "Qu'est-ce que Parallel.ForEach et que fait-il exactement ?"...

47voto

Reed Copsey Points 315315
string[] lines = File.ReadAllLines(txtProxyListPath.Text);

// No need for the list
// List<string> list_lines = new List<string>(lines); 

Parallel.ForEach(lines, line =>
{
    //My Stuff
});

Ainsi, les lignes seront analysées en parallèle, à l'intérieur de la boucle. Si vous voulez une introduction plus détaillée, moins "orientée référence", à la classe Parallel, j'ai écrit une série sur la TPL qui comprend une section section sur Parallel.ForEach .

11voto

Samuel LEMAITRE Points 623

Pour les gros fichiers, utilisez le code suivant (vous êtes moins gourmand en mémoire)

Parallel.ForEach(File.ReadLines(txtProxyListPath.Text), line => {
    //Your stuff
});

6voto

Prince Prasad Points 770

Ces lignes ont fonctionné pour moi.

string[] lines = File.ReadAllLines(txtProxyListPath.Text);
var options = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount * 10 };
Parallel.ForEach(lines , options, (item) =>
{
 //My Stuff
});

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X