web-dev-qa-db-fra.com

Pourquoi Parallel.ForEach n'exécute-t-il pas plusieurs threads?

Aujourd'hui, j'ai essayé de faire de l'optimisation à l'instruction foreach, qui fonctionne sur XDocument.

Avant optimisation:

foreach (XElement elem in xDoc.Descendants("APSEvent").ToList())
{
    //some operations
}

Après optimisation:

Parallel.ForEach(xDoc.Descendants("APSEvent").ToList(), elem =>
{
    //same operations
});

J'ai vu que .NET dans Parallel.ForEach(...) a ouvert SEULEMENT un thread! En conséquence, la période de Parallel était plus grande que la valeur standard foreach.

Pourquoi pensez-vous que .NET n'a ouvert qu'un seul thread? À cause du verrouillage du fichier? Merci

22
zzfima

C'est pour des raisons de conception que Parallel.ForEach peut utiliser moins de threads que ceux demandés pour obtenir de meilleures performances. Selon MSDN [link]

Par défaut, les méthodes Parallel.ForEach et Parallel.For peuvent utiliser un nombre variable de tâches. C'est pourquoi, par exemple, la classe ParallelOptions a une propriété MaxDegreeOfParallelism au lieu d'une propriété "MinDegreeOfParallelism". L'idée est que le système peut utiliser moins de threads que requis pour traiter une boucle.

Le pool de threads .NET s'adapte de manière dynamique à l'évolution des charges de travail en permettant au nombre de threads de travail pour les tâches parallèles de changer dans le temps. Au moment de l'exécution, le système vérifie si l'augmentation du nombre de threads améliore ou diminue le débit global et ajuste le nombre de threads de traitement en conséquence.

15
grapeot

utilisez-le comme ceci:

int ParallelThreads = 10;
Parallel.ForEach(xDoc.Descendants("APSEvent").ToList(), new ParallelOptions() { MaxDegreeOfParallelism = ParallelThreads }, (myXDOC, i, j) =>
{
 //do whatever you want here 
});
1
SolidSnake

D'après la description du problème, rien n'indique pourquoi la TPL ne génère pas plus de threads. 

Il n'y a aucune preuve dans la question qui soit même le problème. Cela peut être corrigé assez facilement: vous pouvez enregistrer l'ID du fil de discussion, avant d'entrer dans la boucle, et en tant que première chose vous le faites dans votre boucle. 

S'il s'agit toujours du même nombre, c'est que la TPL n'a pas réussi à générer des threads. Vous devriez ensuite essayer différentes versions de votre code et les modifications qui déclenchent la synchronisation de la TPL. Une des raisons pourrait être s'il y a un petit nombre d'éléments dans votre liste. La bibliothèque TPL partitionne votre collection et si vous ne disposez que de quelques éléments, vous risquez de vous retrouver avec un seul lot. Ce comportement est configurable par la voie.

Il se peut que vous preniez un verrou par inadvertance dans la boucle, alors vous verrez beaucoup de chiffres différents, mais pas d'accélération. Ensuite, simplifiez le code jusqu'à ce que le problème disparaisse. 

1
user180326

La méthode parallèle n’est pas toujours plus rapide que la "méthode de l’ancienne mode" http://social.msdn.Microsoft.com/Forums/en-US/parallelextensions/thread/c860cf3f-f7a6-46b5-8a07 -ca2f413258dd

0
polkduran

Oui exactement, Document.Load(...)verrouille le fichier et, en raison de conflits de ressources entre les threads, TPL ne peut pas utiliser la puissance de plusieurs threads. Essayez de charger le XML dans une Stream, puis utilisez Parallel.For(...).

0
NoDisplay