Choix dans quel processeur va s'exécuter un thread

Résolu
jdek Messages postés 22 Date d'inscription samedi 8 mars 2008 Statut Membre Dernière intervention 22 avril 2011 - 3 juin 2008 à 14:14
jdek Messages postés 22 Date d'inscription samedi 8 mars 2008 Statut Membre Dernière intervention 22 avril 2011 - 9 juin 2008 à 18:39
Bonjour,

Voila, j'ai un formulaire qui lance sur demande un thread qui exécute des calculs.
Le problème c'est que ces calculs sont assez longs, 15 s, et pendant ce temps, je souhaite pouvoir naviguer dans mon formulaire.
Donc dans ce threads, de temps en temps, j'ai mis l'instruction : Thread.Sleep(0); qui rend la main au système.
Etant donné que mon formulaire utilise des objets graphiques (avec dégradés, path, ...) donc lourds , j'aimerai que le thread de calcul s'exécute sur l'autre processeur (Dual-Core), plutôt que sur celui où le formulaire s'exécute déjà, car sinon mon formulaire se met à rammer.
Bien sur j'aurai pu diminuer le temps processeur alloué au calcul, en mettant par exemple Thread.Sleep(50); mais ca rallonge le temps de calcul à plusieurs minutes.
Donc j'aimerai savoir si vous connaissez des instructions qui permettent de choisir sur quel processeur va s'exécuter un thread.

Merci

12 réponses

jdek Messages postés 22 Date d'inscription samedi 8 mars 2008 Statut Membre Dernière intervention 22 avril 2011
4 juin 2008 à 16:07
Donc j'ai essayer, et ca marche nikel. C'est juste un peu galère pour trouver le n° du thread car il n'y a que par son numéro système que l'on peut y arriver. En fait, la collection récupérée est triée par ordre de création de chaque thread de l'application.  Pour connaitre le n° d'un thread, il suffit de récupérer le dernier objet ProcessThread de la collection juste après la création du thread,  sachant que dans le processus, une fois l'application lancée, il n'y a pas de création de threads supplémentaires (15 environ au démarrage).

Voila comment j'ai procédé :
...
using System.Diagnostics;
using System.Threading;

..................

            ProcessThreadCollection Collection = Process.GetCurrentProcess().Threads;

            foreach (ProcessThread P_Thread in Collection)
            {
                     //Déplacement de tous les threads du processus sur le processeur 1, (le 2 est réservé pour la mesure)
                P_Thread.ProcessorAffinity = new IntPtr(1);  
            }
           
            Thread_mesure = new Thread(Funct_mesure);
            Thread_mesure.IsBackground = true;
            Thread_mesure.Priority = ThreadPriority.Normal;
            Thread_mesure.Start();
           
            //Récupération du n° du dernier Thread créé, afin de le lancer sur l'autre processeur (donc le 2)
            Collection = Process.GetCurrentProcess().Threads;

            Collection[Collection.Count - 1].ProcessorAffinity = new IntPtr(2);   //Collection.Count-1 correspond au dernier thread

...............

Voila ca peut toujours servir, lorsqu'on veut utiliser les ressources CPU à fond (surtout pour les Dual-Core), sachant qu'il est possible de faire changer le thread de processeur pendant son exécution.  On peut par exemple créer un gestionnaire interne de performance. A voir... Si vous avez des objections, des conseils, je prend volontier ^^.

Jdek
3
sebmafate Messages postés 4936 Date d'inscription lundi 17 février 2003 Statut Membre Dernière intervention 14 février 2014 37
3 juin 2008 à 15:05
hum... Thread.Sleep(...) ne donne pas la main au système ! il met en suspend le thread courrant x millisecondes.

Je te conseille de monter une architecture multhi threading... regarde du coté du BackgroundWorker... voire le Pattern Asynchronous (http://www.csharpfr.com/codes/IMPLEMENTATION-PATTERN-ASYNCHRONOUS_41848.aspx)

Sébastien FERRAND (blog)
Consultant Sénior
[Microsoft Visual C# MVP]
0
jdek Messages postés 22 Date d'inscription samedi 8 mars 2008 Statut Membre Dernière intervention 22 avril 2011
3 juin 2008 à 15:40
Oui, ca met en suspend le thread, mais laisse la main aux autres threads (sinon, ca bloquerai mon formulaire).
Le problème c'est que j'ai besoin d'exécuter au maximum proche du matériel (presque du temps réel), donc je ne peux pas me permettre de gérer  trop d'évènements qui peuvent venir altérer mes calculs.
Avec le BackgroundWorker, est-ce que c'est possible d'attribuer son thread sur un certain processeur ?

Jdek
0
sebmafate Messages postés 4936 Date d'inscription lundi 17 février 2003 Statut Membre Dernière intervention 14 février 2014 37
3 juin 2008 à 15:47
en .net tu ne peux pas attribuer à un processeur donné une tache.
par contre, en multi-threading, les taches s'exécutent parallèle... et le pattern Asynchronous fonctionne super bien, je l'ai utilisé dans de très gros projets...

Sébastien FERRAND (blog)
Consultant Sénior
[Microsoft Visual C# MVP]
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
jdek Messages postés 22 Date d'inscription samedi 8 mars 2008 Statut Membre Dernière intervention 22 avril 2011
3 juin 2008 à 19:59
Ok merci pour l'info, je vais essayer de regarder ca.

jdek
0
jdek Messages postés 22 Date d'inscription samedi 8 mars 2008 Statut Membre Dernière intervention 22 avril 2011
3 juin 2008 à 20:41
Si il y en a que ca intéresse, j'ai imaginé une méthode disons barbare , pour "forcer" la gestion du processeur à faire en sorte que le thread soit exécuté sur le processeur où le programme principal ne s'exécute pas.  Lors du start du thread, on fait tourner "à bloc" le processeur sur lequel est le programme principal, ce qui devrait avoir pour effet le démarrage du thread sur l'autre processeur, comme ca par exemple :
int compteur;
do
{
    compteur++;
    if(compteur == 1000)
    {
       monAutreThread.Start(methodeDeMonAutreThread);
    }
}
while(compteur < 1000);

Bon, on ne peut plus artisanal comme méthode ^^, et je n'ai pas encore essayer.  Disons que pour l'instant c'est la seule méthode que je connaisse, peut être que si l'on peut consulter sur quel processeur est exécuter un thread, il y a moyen de se débrouiller plus méthodiquement.  Je vous tiens au courant.
0
jdek Messages postés 22 Date d'inscription samedi 8 mars 2008 Statut Membre Dernière intervention 22 avril 2011
4 juin 2008 à 11:23
Bon cette méthode marche si le thread est en priorité maximale (Highest), donc on ne peut utiliser cette méthode que si ce thread est le seul à s'exécuter sur le deuxième processeur, sinon il y a risque de fort ralentissement des autres threads.
Je n'est pas encore relevé d'erreur à cette méthode, mais ca pourrai bien arrivé.
(Si un autre programme utilise beaucoup la CPU, cette méthode risque de ne pas marcher).

Jdek
0
sebmafate Messages postés 4936 Date d'inscription lundi 17 février 2003 Statut Membre Dernière intervention 14 février 2014 37
4 juin 2008 à 11:33
c'est surtout pas propre...

sincèrement, je préfère laisser l'os gérer lui-même les threads.

Sébastien FERRAND (blog)
Consultant Sénior
[Microsoft Visual C# MVP]
0
jdek Messages postés 22 Date d'inscription samedi 8 mars 2008 Statut Membre Dernière intervention 22 avril 2011
4 juin 2008 à 11:51
Je suis bien d'accord,
mais il semble que .net rend possible le changement de processeur : http://msdn.microsoft.com/fr-fr/library/system.diagnostics.processthread.idealprocessor(VS.80).aspx
à essayer.

Jdek
0
cs_coq Messages postés 6349 Date d'inscription samedi 1 juin 2002 Statut Membre Dernière intervention 2 août 2014 101
7 juin 2008 à 17:26
Salut,

"Pour connaitre le n° d'un thread, il suffit de récupérer le dernier objet ProcessThread de la collection juste après la création du thread"
Heu non, je ne serais pas aussi confiant, il suffit qu'un autre thread crée un nouveau thread entre temps et c'est la fin. En plus je ne suis pas certains que l'ordre de la collection soit garanti.

Le plus "sur" est probablement d'utiliser directement SetThreadAffinityMask en P/Invoke.
Mais ici le plus gros problème est de faire le parallèle entre le thread managé et le thread physique qui est dessous (si c'est bien un thread physique qui est en dessous d'ailleurs).
Bien garder à l'esprit que ce genre de manipulation est à proscrire en dehors du host standard. On manipule le thread réel, ce qui peut être assez problématique si hébergé dans des hosts comme par exemple SQL Server 2005 (voir Thread.BeginThreadAffinity notamment).

Il n'est même pas certains que le thread managé soit implémenté en temps que thread "standard" par le host alternatif (voir Fiber), ce qui peut justement être le cas avec SQL Server il me semble (pas sûr).

/*
coq
MVP Visual C#
CoqBlog
*/
0
cs_coq Messages postés 6349 Date d'inscription samedi 1 juin 2002 Statut Membre Dernière intervention 2 août 2014 101
7 juin 2008 à 17:27
D'ailleurs à y réfléchir, je me demande si le host standard n'est pas lui aussi soumis à variations, notamment d'une version du CLR à l'autre.

/*
coq
MVP Visual C#
CoqBlog
*/
0
jdek Messages postés 22 Date d'inscription samedi 8 mars 2008 Statut Membre Dernière intervention 22 avril 2011
9 juin 2008 à 18:39
salut,
ok merci pour l'info.
Bien sur la méthode que j'ai posté plus haut fonctionne, mais ce n'est pas de la programmation sure, et elle risque de dépendre d'autres paramètres.
Je n'ai pas le temps actuellement pour faire des tests, mais si j'arrive à faire marcher cette méthode plus sure, je posterai encore ici.

Jdek
0
Rejoignez-nous