18

Je dirigeais une boucle multi-thread:Est-il possible de changer parallelOptions.MaxDegreeOfParallelism lors de l'exécution d'un Parallel.ForEach

protected ParallelOptions parallelOptions = new ParallelOptions(); 

parallelOptions.MaxDegreeOfParallelism = 2; 
Parallel.ForEach(items, parallelOptions, item => 
{ 
// Loop code here 
}); 

Je veux changer le parallelOptions.MaxDegreeOfParallelism lors de l'exécution de la boucle parallèle réduire ou augmenter un nombre de threads.

parallelOptions.MaxDegreeOfParallelism = 5; 

Cela ne semble pas augmenter les threads. Quelqu'un a-t-il une idée?

+0

Pouvez-vous expliquer pourquoi vous voudriez faire cela? Il augmentera déjà le nombre de threads jusqu'à atteindre le maximum spécifié si nécessaire, ou utilisera moins, le cas échéant. –

+1

Principalement pour gâcher l'application lorsqu'elle utilise trop de ressources sur un serveur partagé. Je fais fonctionner le serveur à 100% ce qui dégrade la réactivité des autres applications sur les serveurs. –

+0

S'agit-il d'un problème lié au processeur ou d'un autre type de 'disque'? –

Répondre

3

Je ne m'attendrais pas à ce qu'il soit possible de changer le degré de parallélisme après avoir appelé ForEach. Si je comprends bien, ForEach va déterminer combien de threads il peut créer, créer autant de partitions, et créer les threads pour fonctionner sur ces partitions. Il n'y a aucun point où il peut dire, "Oh, attendez, il a changé notre allocation de ressources, permettez-moi de re-partitionner le tableau et de réaffecter les threads."

+0

Oui, bien sûr, je suis d'accord avec votre compréhension, mais pourriez-vous s'il vous plaît ajouter un lien de référence? –

6

Le problème avec même essayer de faire ceci est que c'est un problème difficile. Pour commencer, comment observez-vous l'utilisation du processeur et du disque de manière fiable? Échantillonnage CPU peu souvent donnera une mauvaise image de ce qui se passe réellement et l'utilisation du disque d'échantillonnage est encore plus difficile. Deuxièmement, quelle est la granularité de vos tâches et à quelle fréquence pouvez-vous rapidement changer le nombre de tâches en cours. Troisièmement, les choses changent rapidement avec le temps, vous devez donc appliquer une sorte de filtrage à vos observations. Quatrièmement, le nombre idéal de threads dépendra du processeur sur lequel le code est exécuté. Cinquièmement, si vous allouez trop de threads, vous serez en train de les écraser au lieu de faire un travail utile. Voir http://msdn.microsoft.com/en-us/magazine/ff960958.aspx pour une discussion sur la façon dont le pool de threads dans .NET gère la tâche complexe consistant à décider du nombre de threads à utiliser. Vous pouvez également utiliser un réflecteur et regarder le code utilisé par TPL pour allouer des threads et éviter les changements de contexte inutiles. C'est complexe et cela ne prend même pas en compte l'accès au disque!

Vous pourriez plutôt essayer d'exécuter les tâches sur un thread de priorité inférieure (créer votre propre TaskScheduler qui exécute des threads avec une priorité inférieure à la normale est en fait assez facile). Cela permettra au moins de faire fonctionner 100% du CPU sans affecter le reste du système. Se moquer des priorités des threads est en lui-même lourd de problèmes, mais s'il s'agit d'une tâche purement contextuelle, cela peut être simple et peut aider.

Souvent, cependant, l'utilisation du disque est le vrai coupable quand il s'agit d'autres applications souffrant d'une application gourmande. Windows peut allouer la CPU de manière équitable entre les applications, mais lorsque l'accès au disque est relativement lent, c'est une toute autre affaire. Au lieu d'essayer d'ajuster dynamiquement le nombre de threads que vous avez en cours d'exécution, vous devrez peut-être simplement limiter votre application de sorte qu'elle n'accède pas trop souvent au disque. C'est quelque chose que vous pouvez faire sans changer le nombre de threads actifs.

Vous pouvez également consulter SetPriorityClass pour informer le système d'exploitation que votre processus est moins important que les autres applications exécutées sur le système. Pour plus d'informations, voir How can I/O priority of a process be increased?. Mais cela suppose que tout votre processus est moins important, pas seulement cette partie de celui-ci.

Questions connexes