TRAITER UN FOREACH EN PARALLÈLE

Tilois Messages postés 721 Date d'inscription dimanche 10 juin 2001 Statut Membre Dernière intervention 27 mars 2011 - 31 déc. 2008 à 10:13
blodja743 Messages postés 5 Date d'inscription samedi 20 janvier 2007 Statut Membre Dernière intervention 14 janvier 2010 - 14 janv. 2010 à 18:20
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/48820-traiter-un-foreach-en-parallele

blodja743 Messages postés 5 Date d'inscription samedi 20 janvier 2007 Statut Membre Dernière intervention 14 janvier 2010
14 janv. 2010 à 18:20
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.
maitredede Messages postés 153 Date d'inscription vendredi 9 août 2002 Statut Membre Dernière intervention 18 septembre 2009
14 janv. 2010 à 18:05
Là, ça n'est plus de mon ressort ;) Bon courage :)
blodja743 Messages postés 5 Date d'inscription samedi 20 janvier 2007 Statut Membre Dernière intervention 14 janvier 2010
14 janv. 2010 à 17:39
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éé
maitredede Messages postés 153 Date d'inscription vendredi 9 août 2002 Statut Membre Dernière intervention 18 septembre 2009
14 janv. 2010 à 15:05
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...
blodja743 Messages postés 5 Date d'inscription samedi 20 janvier 2007 Statut Membre Dernière intervention 14 janvier 2010
14 janv. 2010 à 13:20
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.
maitredede Messages postés 153 Date d'inscription vendredi 9 août 2002 Statut Membre Dernière intervention 18 septembre 2009
14 janv. 2010 à 12:00
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.
blodja743 Messages postés 5 Date d'inscription samedi 20 janvier 2007 Statut Membre Dernière intervention 14 janvier 2010
14 janv. 2010 à 11:55
Salut , j'utilise un foreach classique qui fonctionne bien mais j'ai l'impression qu'il utilise pas tous les procs de la machine.
maitredede Messages postés 153 Date d'inscription vendredi 9 août 2002 Statut Membre Dernière intervention 18 septembre 2009
13 janv. 2010 à 21:36
Salut,
Essaie ton code avec un foreach classique, si ça se trouve, c'est ton encodeur qui plante sans raison...
blodja743 Messages postés 5 Date d'inscription samedi 20 janvier 2007 Statut Membre Dernière intervention 14 janvier 2010
13 janv. 2010 à 19:47
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
maitredede Messages postés 153 Date d'inscription vendredi 9 août 2002 Statut Membre Dernière intervention 18 septembre 2009
11 janv. 2009 à 19:19
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)
r2d2tm Messages postés 6 Date d'inscription mercredi 16 janvier 2008 Statut Membre Dernière intervention 10 janvier 2009
10 janv. 2009 à 16:05
"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
cs_coq Messages postés 6349 Date d'inscription samedi 1 juin 2002 Statut Membre Dernière intervention 2 août 2014 101
10 janv. 2009 à 12:23
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.
maitredede Messages postés 153 Date d'inscription vendredi 9 août 2002 Statut Membre Dernière intervention 18 septembre 2009
9 janv. 2009 à 20:06
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...
r2d2tm Messages postés 6 Date d'inscription mercredi 16 janvier 2008 Statut Membre Dernière intervention 10 janvier 2009
9 janv. 2009 à 17:05
"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
maitredede Messages postés 153 Date d'inscription vendredi 9 août 2002 Statut Membre Dernière intervention 18 septembre 2009
9 janv. 2009 à 16:46
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 ?
r2d2tm Messages postés 6 Date d'inscription mercredi 16 janvier 2008 Statut Membre Dernière intervention 10 janvier 2009
9 janv. 2009 à 16:26
"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
}
}
}

}
maitredede Messages postés 153 Date d'inscription vendredi 9 août 2002 Statut Membre Dernière intervention 18 septembre 2009
9 janv. 2009 à 16:10
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.
r2d2tm Messages postés 6 Date d'inscription mercredi 16 janvier 2008 Statut Membre Dernière intervention 10 janvier 2009
9 janv. 2009 à 15:45
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
maitredede Messages postés 153 Date d'inscription vendredi 9 août 2002 Statut Membre Dernière intervention 18 septembre 2009
9 janv. 2009 à 15:26
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 ?
r2d2tm Messages postés 6 Date d'inscription mercredi 16 janvier 2008 Statut Membre Dernière intervention 10 janvier 2009
9 janv. 2009 à 11:36
à 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
maitredede Messages postés 153 Date d'inscription vendredi 9 août 2002 Statut Membre Dernière intervention 18 septembre 2009
31 déc. 2008 à 11:01
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
Tilois Messages postés 721 Date d'inscription dimanche 10 juin 2001 Statut Membre Dernière intervention 27 mars 2011 7
31 déc. 2008 à 10:13
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
Rejoignez-nous