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();
}
}
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
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. –
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