Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

TRAITER UN FOREACH EN PARALLÈLE


Information sur la source

Catégorie :Astuces Source .NET ( DotNet ) Classé sous : foreach, parallel, boucle, thread Niveau : Initié Date de création : 29/12/2008 Date de mise à jour : 29/12/2008 16:39:37 Vu / téléchargé: 2 593 / 132

Note :
Aucune note

Commentaire sur cette source (13)
Ajouter un commentaire et/ou une note


Description

Faire des boucles ForEach, c'est pratique. Mais si on a beaucoup d'éléments à traiter, pourquoi ne pas répartir la charge sur tous les processeurs du système ?

Ce petit bout de code permet d'exécuter du code sur chaque élément d'une collection, en parallèle sur chaque processeur du système.
 

Source

  • //On a une collection d'objets
  • IEnumerable<MaClass> collection;
  • //L'action à réaliser
  • Action<MaClass> action = delegate(MaClass item)
  • {
  • Console.WriteLine(item.ToString());
  • }
  • //L'appel de la boucle
  • try
  • {
  • Parallel.ForEach<MaClass>(collection, action);
  • }
  • catch(ParallelException ex)
  • {
  • //On peut récupérer pour chaque item l'exception dans son traitement
  • // via ex.Exceptions
  • }
//On a une collection d'objets
IEnumerable<MaClass> collection;

//L'action à réaliser
Action<MaClass> action = delegate(MaClass item)
{
    Console.WriteLine(item.ToString());
}

//L'appel de la boucle
try
{
    Parallel.ForEach<MaClass>(collection, action);
}
catch(ParallelException ex)
{
    //On peut récupérer pour chaque item l'exception dans son traitement
    // via ex.Exceptions
}

Conclusion

C'est un peu un clone de Microsoft Parallel Extensions, mais le but était didactique, et aussi parce que je n'ai pas de dépendance au framework 3.0.
 

Fichier Zip

Pour les "Membres Club", vous pouvez télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip

Historique

29 décembre 2008 16:39:37 :
Source d'exemple

Commentaires et avis

signaler à un administrateur
Commentaire de Tilois le 31/12/2008 10:13:41

Bonjour,
Il me semble que tu oublies de préciser qu'il faut avoir les extensions PFX pour .NET.
http://msdn.microsoft.com/fr-fr/concurrency/default(en-us).aspx

signaler à un administrateur
Commentaire de maitredede le 31/12/2008 11:01:20

Bonjour,

Le code que je montre, c'est justement pour ne pas utiliser les PFX.
J'ai codé le moyen de faire un ForEach, en traitant chaque item de ta collection en parallèle.
J'ai juste comparé mon code au PFX car c'est dans l'idée la même chose, mais je ne vais pas aussi loin que la lib PFX.

Tout dépend de ce que tu veux faire... Soit tu a juste besoin d'améliorer les perfs dans ton code en traitant tes items en parallèle et mon va bien, soit tu a besoin de PLink, et là c'est PFX... Sans oublier que ma lib n'a pas besoin du framework 3.0 pour fonctionner, c'est du pur 2.0

signaler à un administrateur
Commentaire de r2d2tm le 09/01/2009 11:36:42

à ma connaissance les threads/processeurs gérés par le framework sont des entités "logiques" ils ne correspondent pas aux "thread/processeurs" physiques.

Chacun des threads créés sont répartis sur tous les processeurs en même temps.


voila pour définir l'affinité :
http://msdn.microsoft.com/en-us/library/system.diagnostics.processthread.processoraffinity.aspx



signaler à un administrateur
Commentaire de maitredede le 09/01/2009 15:26:59

Je pense que les threads/processeurs gérés par le framework correspondent aux threads/processeurs physiques (à ceci près que l'hyperthreading intel est vu par windows comme un deuxième processeur, alors qu'il n'y en a qu'un).
Le framework repose sur le système, et donc gère les threads de manière logique au sein du framework. Donc je comme pense qu'un thread du framework est basé sur un thread windows natif, il agit à l'identique.

Donc pour faire un traitement en rarallèle sur un système à dual-core, il faut lancer 2 threads, un sur chaque proc en théorie. En pratique, c'est le noyau windows qui va répartir la charge sur ses procs (en général 50-50).

Après, tu peux choisir sur quel core ton process va s'exécuter. Et tu ne gagne rien à forcer ton process à s'exécuter sur un seul core alors que tu en a deux (ou plus).

Un cas concret d'utilisation : du raytracing. J'ai testé un raytracer C#. Deux boucles for imbriquées, temps de rendu : 60s. Ma boucle foreach parallèle, sur un processeur dual-core, avec légères modifications pour les accès concurentiels, et pouvoir traiter en parallèle : 30s. Concluant ?

signaler à un administrateur
Commentaire de r2d2tm le 09/01/2009 15:45:15

On ne s'est pas compris, je suis d'accord avec le gain de perf, mais la description faite laisse a penser qu'on affecte un travaille a chaque processeur physique.

vous écrivez :
"en parallèle sur chaque processeur du système."


je ne joue pas sur les mots mais l'association traitement / proc physique est un sujet différent de ce celui que vous traitez.
Je vous ai mis le lien vers le processoraffinity par ce que la source serait vraiment plus complète avec une vraie association traitement/proc physique.

Au delà de ça bravo pour l'effort

signaler à un administrateur
Commentaire de maitredede le 09/01/2009 16:10:53

Effectivement, on peut le comprendre par une affectation d'une tâche par processeur. Mais à ma connaissance, il n'est pas possible de gérer l'affinité processeur au niveau du thread. C'est Windows qui gère cette affinité au niveau process.

En fait, il faut comprendre que les tâches sont réalisées en parallèle, réparties sur les processeurs du système, mais c'est Windows qui gère la répartition.

Pour aller plus loin dans les détails (pour ceux qui sont curieux) : un processeur n'est pas capable de faire des tâches en parallèle (ou un coeur dans le cas des multi-core). Afin de faire des systèmes d'exploitation multi-tâche, chaque tâche est découpée en petit morceaux. Et à intervals réguliers, le noyau du système d'exploitation interrompt une tâche pour donner la main à une autre.
Dans le cas appliqué à des tâches longues et sur un processeur multi-core, le système d'exploitation envoie ces "morceaux de tâche" sur les processeurs, en fonction de la charge de chacun. Il n'est donc pas possible de choisir à l'avance sur quel processeur s'exécutera un thread (une tâche). Un exemple pratique : lancer un jeu (Half-life 2) et regarder les courbes de charge processeur sur un système dual-core. Chaque processeur est chargé à 50% car l'OS réparti la charge sur tous les processeurs. Dans un programme multi-thread, le système peut exécuter chaque thread sur un processeur. Par exemple, avec le jeu SuperCommander, le jeu calcule l'affichage sur un processeur, pendant qu'il calcule l'intelligence des unités sur un autre processeur.

Enfin bref, merci bien pour l'appréciation de ma contribution.

signaler à un administrateur
Commentaire de r2d2tm le 09/01/2009 16:26:39

"Donc je comme pense qu'un thread du framework est basé sur un thread windows natif" => ce n'est pas le cas...


Je vous donne le code pour le faire :

class AffecterUnThreadAUnProc
    {
        [DllImport("kernel32")]
        static extern int GetCurrentThreadId();

        static void Main()
        {
            Thread t = new Thread(new ThreadStart(monThread));
            t.Start();
            t.Join();
        }

        static void monThread()
        {
   int idCurrentThread = GetCurrentThreadId();

            foreach (ProcessThread th in Process.GetCurrentProcess().Threads)
            {
                if (th.Id == idCurrentThread  )
                {
                    th.ProcessorAffinity = (IntPtr)(1); // Affecte le thread au processeur n°1
                }
            }
        }

    }


signaler à un administrateur
Commentaire de maitredede le 09/01/2009 16:46:47

Ce code est sensé produire quoi ?
A première vue, ça permet de choisir l'affinité du thread sur un processeur. En quoi est-ce que ça affecte le fait que ça soit un thread du framework par rapport à un thread natif ?

signaler à un administrateur
Commentaire de r2d2tm le 09/01/2009 17:05:14

"Ce code est sensé produire quoi ? A première vue,..."
question + réponse :-)

aucun lien avec les thread du framework et natifs, c'était pour le compélement à votre programme.

Pour la question des thread du framework, faites une application monothread et faite la fonctionner sur un dual core et je pense que vous changerez d'avis sur l'assertion "thread du framework est basé sur un thread windows"

bonne soirée

signaler à un administrateur
Commentaire de maitredede le 09/01/2009 20:06:24

Pour le bout de code, je m'en servirai pour ajouter une surcharge dans ma lib. Du coup, Merci :o)

Par contre, pour cette application monothread, que suis-je sensé observer ? Mis à part qu'une boucle infinie me consomme 50% de chaque core, et que j'ai le même comportement sur des applications natives...

signaler à un administrateur
Commentaire de coq le 10/01/2009 12:23:51 administrateur CS

Salut,

Le thread managé (classe Thread) n'est pas forcément un thread "Win32" (CreateThread etc).
Ce qui se trouve en dessous d'un thread managé dépend de la manière dont l'hôte du CLR l'a implémenter.
Pour un hôte tel que SQL Server qui peut fonctionner en mode Fiber, il se peut qu'à terme (à l'heure actuelle sur des versions 2005/2008 ce n'est pas le cas pour le code .NET utilisateur, vu qu'on ne peut l'utiliser si le mode Fiber est actif) les threads managés soit en fait des fibers.

Donc même si vous avez peu de chances (en développement "grand public") de rencontrer autre chose qu'un thread en dessous d'un thread managé, ne partez pas du principe que c'est toujours le cas.

signaler à un administrateur
Commentaire de r2d2tm le 10/01/2009 16:05:04

"que suis-je sensé observer ? Mis à part qu'une boucle infinie me consomme 50% de chaque core"

Un thread systeme est associé a un seul processeur ou coeur, donc si pour une application monothread les 2 processeurs sont occupés cela demontre que l'application monothread n'en n'est pas une. L'OS a réorganisé en plusieurs threads pour répartir la charge sur tous les processeurs. cqfd

signaler à un administrateur
Commentaire de maitredede le 11/01/2009 19:19:42

Merci pour ton expliquation Coq :o)

R2D2TM : Donc si j'en crois ton explication, une application mono-thread ne doit s'exécuter que sur un seul processeur. Or, comment se fait-il qu'une vrai application native mono-thread s'exécuté à 50% sur chaque processeur (selon les courbes d'occupation des processeurs du gestionnaire de tâche) ?
Je pense que c'est plutôt du au fait que l'OS envoie un "morceau" de programme un coup sur un processeur, un coup sur l'autre... Nulle part je n'ai vu de règle disant qu'un thread devait s'exécuter intégralement sur le même processeur... Rien n'empèche l'OS d'alterner l'exécution du code sur chacun des processeurs, sous réserve qu'on garde la séquentialité originale du code...
J'admets que je peux avoir tord, mais il me faudra plus qu'un "cqfd" pour me le démontrer. :o)

Ajouter un commentaire

Discussions en rapport avec ce code source dans le forum

"sauter par dessus" un foreach?? [ par immerczeck ] Bonjour!j'ai de nouveau un petit probl&#232;me, mais j'avoue, celui-l&#224;, je sais plus quoi faire : est ce qu'il pourrait y avoir une raison pour q Stopper une boucle [ par Yxion ] Salut, Je suis assez novice dans le sujet, mais j'ai cherché hier toute la journée et j'ai rien trouvé. Voila mon pb :J'ai boucle qui peut etr sortir d'une boucle foreach [ par yohan49 ] jsute une kestion toute beteje cherche comment on sort d'une boucleen vb.net : exit foren C# : ???? Thread boucle [ par fredspv ] Bonjour,Je parcours une listbox contenant des fichiers,&#224; l'aide d'une boucle for,&nbsp;pour faire du publipostage avec Word. J'ai un bouton qui p Lancement et Création de Thread [ par skyline86 ] Bonjour, je viens vers vous car j'ai un problème avec mon programme en C#.Je vous explique d'abord de le but du programme :Ce programme doit pouvoir é Pb Boucle Infini!!!!!!!!!!! [ par yanis7518 ] Salutvoila j'ai 2 dossier qui sont aliment&#233; en permanence en fichier txtle but de mon appli est de tourner en boucle et de traiter&nbsp; les fich actualisation de la form a partir d'un thread. [ par bwoufy82 ] Bonjour a tous.Voiladepuis 3 jours je n arrive pas a trouver comment faire pour que mon thread accede a ma form.J'esxplique se que je cherche a faire Probleme arret programme | Thread [ par ChamY ] Bonjour,j ai un ptit probleme pour terminer mon programme.Un de mes boutons lance une tache de ma classe annexe. Cette tache ouvre un socket et attend Thread time [ par SfyLer ] Bonjour &#224; tous, j'ai un petit probl&#232;me pour mettre &#224; jour l'heure dans mon IHM mais je ne comprend pas d'o&#251; sa peux venir: &nbsp Exécution sous Thread spécifique [ par thegitch ] Bonjour à tous,Comment, depuis un thread B, exécuter une méthode sous un thread A ? Je m'explique.Le thread A est le thread principal, le main, le thr


Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Téléchargements

Comparez les prix Nouvelle version

Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 1,061 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.