2010-08-20 3 views
4

Je travaille sur une petite simulation qui s'exécute sur mon poste de travail à 8 cœurs. La simulation consiste à modéliser les interactions entre un grand nombre de nœuds indépendants. Pendant une phase, j'ai besoin d'effectuer une série d'opérations atomiques simples à chaque nœud en parallèle. J'ai utilisé Parallel.ForEach de System.Threading.Tasks pour appliquer l'opération simultanément à chaque nœud dans la liste de tous les nœuds.C# Séparer efficacement les tâches entre les cœurs

Cela a bien fonctionné pour les 100 à 500 nœuds que j'ai utilisés pour les tests. La charge était très bien équilibrée avec tous les noyaux constamment utilisés. Malheureusement, lorsque je tente d'exécuter la simulation avec l'ensemble de données principal (plus de 5000 nœuds), tout va mal. Les 8 coeurs restent inactifs la plupart du temps, atteignant 100% toutes les quelques secondes, puis revenant à 1% d'utilisation. Après quelques minutes, une exception OutOfMemoryException est levée et le programme se bloque.

Je ne suis pas complètement sûr de ce qui ne va pas, mais reste suspect que mon code actuel engendre beaucoup plus de threads que ce qui serait optimal pour la tâche. Je pense que la méthode idéale serait que le modèle détecte le nombre de cœurs disponibles N, partitionne la liste des nœuds en N segments, puis génère N threads, donnant à chaque thread une partition séparée de la liste.

Ce que je voudrais demander, c'est si c'est une bonne solution au problème, existe-t-il de meilleurs, et comment devrait-il être implémenté en C#? Tous les conseils ou commentaires sont les bienvenus.

EDIT: Code échantillon demande

Parallel.ForEach(listOfNodes, tempNode => 
{ 
    tempNode.foo(); 
}); 

<snip> 

void foo() 
{ 
    foreach(myType bar in listOfmyType) 
    { 
     if (bar.isActive) 
      setNodeActive(); 
    } 
} 
+2

Un exemple de code court mais complet qui démontre le problème serait utile, sinon tout ce que vous êtes susceptible d'obtenir est la spéculation. – LBushkin

+1

Vous manquez de mémoire; Si vous thrash le fichier d'échange, l'utilisation du processeur diminue considérablement parce que le processeur attend le disque la plupart du temps. Ainsi, le comportement de votre machine peut être expliqué; le remède est de réduire l'utilisation de la mémoire. –

+0

LBushkin, j'ai pensé à ça, mais le code est tellement générique que ça ne semble pas être utile. C'est juste: Parallel.ForEach (listOfNodes, tempnode => { tempnode.foo() }); – Mandelbrot

Répondre

3

Voir ce fil, qui porte sur la limitation du nombre de threads qui Parallel.For utilise pour éviter la famine de mémoire:

http://connect.microsoft.com/VisualStudio/feedback/details/534571/parallel-foreach-may-create-an-inordinate-number-of-threads

Je voudrais essayer la mise ParallelOptions.MaxDegreeOfParallelism à environ 500, et de voir ce qui se passe.

+1

500 semble toujours horriblement élevé, pouvez-vous expliquer? Mon estimation serait de 10-20 (8 cœurs, peu ou pas d'E/S). –

+0

Oui, j'aurais pensé que 8 ou 10 seraient une bonne limite. Pourquoi 500 serait une bonne estimation de départ? – Mandelbrot

+0

Parce que vous avez dit que cela fonctionnait bien avec 500 nœuds. Il ne doit pas être 500. J'ai un service Windows qui exécute des tâches de longue durée en arrière-plan derrière un site Web. Il utilise un objet 'ThreadPool'. J'ai fait des tests dessus, et j'ai trouvé que le nombre idéal de threads en cours d'exécution est le nombre de cœurs dans la machine, donc YMMV. –

2

Je pense que la méthode idéale serait pour le modèle pour détecter le nombre de noyaux disponibles N, partitionner la liste des noeuds en segments N, puis engendrer N threads, donnant à chaque thread une partition distincte de la liste.

Ce qui est exactement ce que fait Parallel.ForEach, donc il doit y avoir un autre problème.

Il va être très difficile de trouver un meilleur système (gestion des fils). Mais vous pouvez utiliser des planificateurs personnalisés dans la bibliothèque de tâches.

+0

Hm, j'avais peur de ça. Merci pour l'information. – Mandelbrot

Questions connexes