begin process at 2012 02 08 04:39:22
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Astuces

 > TRAITER UN FOREACH EN PARALLÈLE

TRAITER UN FOREACH EN PARALLÈLE


 Information sur la source

Note :
Aucune note
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é :6 630 / 244

Auteur : maitredede

Ecrire un message privé
Ce membre participe au partage de revenus publicitaires
Commentaire sur cette source (22)
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

Les Membres Club peuvent 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

 Sources du même auteur

Source avec Zip Source .NET (Dotnet) CHATBOX : AFFICHAGE DE TEXTE AVEC SMILEYS
Source avec Zip Source .NET (Dotnet) STREAM QUI LIMITE LA BANDE PASSANTE
Source avec Zip Source .NET (Dotnet) COUCHE D'ACCÈS AUX DONNÉES SIMPLIFIÉE
Source avec Zip Source .NET (Dotnet) MOTEUR DE PLUGINS AVEC CHARGEMENT/DÉCHARGEMENT

 Sources de la même categorie

Source avec Zip Source .NET (Dotnet) DIFFÉRENTIELLE ENTRE DEUX COLLECTION par morphey_83
Source avec Zip Source avec une capture Source .NET (Dotnet) RICHTEXTBOX POUR COLORATION SYNTAXIQUE EN TEMPS REEL par Renfield
Source avec Zip Source avec une capture Source .NET (Dotnet) TRANSFORMER UN PROGRAMME EN SERVICE par xavh44
Source avec Zip Source .NET (Dotnet) [C# ET T4] TEMPLATE DE VIEW MODEL POUR LE PATTERN MVVM par Kite37
Source .NET (Dotnet) EXEMPLE D'UTILISATION D'UN OCX SANS DECLARATION PREALABLE DA... par yohan49

 Sources en rapport avec celle ci

Source avec Zip Source .NET (Dotnet) AFFICHAGE DE VALEUR PROVENANT D'U THREAD DANS UN FORMULAIRE par Nyuki
Source avec Zip Source avec une capture Source .NET (Dotnet) CLIENT IRC QUI LIT À VOIX HAUTE par pigedanslelac
Source avec Zip Source .NET (Dotnet) THREADWORKER par krimog
Source avec Zip Source .NET (Dotnet) UTILITAIRE ITUNE par zanzan
Source .NET (Dotnet) EACHPARALLEL par SoaR245

Commentaires et avis

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

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

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



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 ?

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

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.

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
                }
            }
        }

    }


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 ?

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

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...

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.

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

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)

Commentaire de blodja743 le 13/01/2010 19:47:32

Salut "maitreded"e et merci pour ton code, j'ai un souci qui est le suivant j'essaie d'encodé des fichiers audio d'un format à un autre ensuite en utilisant ton code je vois bien que fonction du nombre de processeur il y a autant de threads par contre dans la liste des titres il y a certains qui sont pas encodé ou plutot pas totalement encodé comme si le process en cour avait été interrompu par les suivant ou que les threads abandonne leur tache actuel dès qu'un des deux à fini le sien afin de le rattrapé. désolé mais je suis un peu perdu .  Merci

Commentaire de maitredede le 13/01/2010 21:36:36

Salut,
Essaie ton code avec un foreach classique, si ça se trouve, c'est ton encodeur qui plante sans raison...

Commentaire de blodja743 le 14/01/2010 11:55:18

Salut , j'utilise un foreach classique qui fonctionne bien mais j'ai l'impression qu'il utilise pas tous les procs de la machine.

Commentaire de maitredede le 14/01/2010 12:00:54

Un foreach classique n'utilisera qu'un seul proc... Mon bout de code te permet d'utiliser tous les procs...

Le fait d'utiliser un foreach classique, c'est pour voir si c'est pas un de tes items qui plante... Si t'as un item qui plante, alors c'est pas ma lib qui est en cause, mais ton encodeur.

Commentaire de blodja743 le 14/01/2010 13:20:57

ce n'est pas un mes items qui plante vu que a chaque test ce n'est pas le meme titre ni le meme nombre qui ne sont encodés.
je me demande si dans l'optique de faire les traitements en parallèle , meme si un thread n'a pas terminé sa tache l'abandonne afin de suivre l'autre sur les items suivants.
Désolé si c'est pas cohérent mais je cherche une explication a ce phénomène.

Commentaire de maitredede le 14/01/2010 15:05:23

Si ça ne sont pas les mêmes items qui sont encodées, ce que tu peux faire, c'est loguer dans un fichier TOUTES les infos nécessaires qui pourraient t'aider à savoir si ton encodage fonctionne : titre encodé, exceptions, etc...
Dans mon code, l'item suivante n'est traitée que si une item a terminé et si on ne dépasse pas le nombre d'items à traiter en même temps...

Commentaire de blodja743 le 14/01/2010 17:39:12

Merci mais je l'ai fait et l'encodage se déroule entier pour certains et à un certains pourcentages pour d'autres , je crois que a un moment ou a un autre le processus d'encodage est interrompu peut être par les nouveaux processus créé

Commentaire de maitredede le 14/01/2010 18:05:10

Là, ça n'est plus de mon ressort ;) Bon courage :)

Commentaire de blodja743 le 14/01/2010 18:20:03

merci a toi désolé  j'avais pas fait attention a une methode qui tuait mon outil d'encodage et donc forcement la second instance en parallèle vu que il ya forcement un qui finira le premier.

Dslé merci.

 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 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 é sortir d'une boucle foreach [ par yohan49 ] jsute une kestion toute beteje cherche comment on sort d'une boucleen vb.net : exit foren C# : ???? Lancer un Thread dans une boucle for [ par romain60112 ] Bonjour, Je rencontre un problème pour lancer mon thread sur dans une boucle for; Le thread c'est l'affichage du % d'avancement voici mon code : pr 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 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 Boucle Foreach sur ligne sélectionner d'un GridView [ par ZackLaMenace ] Bonjour à tous et merci d'avance pour votre aide. J'ai un soucis, qui me semble pourtant bête comme la pluie, mais j'ai cherché et je sèche :-(. Je Thread.Sleep [ par zakaria1158 ] Bonjour, [*] voici mon code : private void button1_Click(object sender, EventArgs e) { textBox1.Text= "texte"; Syst 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


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Février 2012
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
272829    

Consulter la suite du CalendriCode

Photothèque

 
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

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 1,435 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales