IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

[Thread] Test et interprétation


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    198
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 198
    Par défaut [Thread] Test et interprétation
    Bonjour,
    j'ai expérimenté les threads en C# et je n'arrive pas à interpréteur certains résultats et d'autre je n'en suis pas sur. J'ai donc une classe ThreadTester avec un attribut _numIteration qui sera décrémenté dans la méthode Treatment à chaque passage.

    1) Constatation A : J'ai remarqué que le temps pour éxecuter X tours de boucles n'était pas divisé par le nombre de thread mais avait même tendance à être encore plus élevé ( 38 sec pour 2 threads, 19 sec pour 1 thread par exemple).
    Constatation B : Les deux CPU du core 2 duo sont à 100% d'utilisation.
    Explication : Je pense que c'est tout simplement parce que les threads ne s'exécute pas en parallèle mais un à la fois sur le même CPU.
    Mais alors pourquoi, si les 2 CPU sont à 100% le temps n'est pas divisé en deux mais plutot multiplié?? Un changement de contexte ferait perdre autant de temps ?

    2) Constatation : La somme des décrémentations est quasi toujours supérieur à _numIteration initial si au moins 2 threads ont eu le temps de décrémenter.
    Explication : Je n'en sais rien du tout.

    3) Question : Quelle est la meilleur solution pour multiplier le gain de temps par le nombres de Threads ?

    Au passage, n'hésitez pas à faire d'autres critiques sur le code qui n'ont rien avoir avec le sujet.


    Merci d'avance


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
     
    class ThreadTester
        {
            long _numIteration = 0;
            DateTime _tic ; //start time
     
            public ThreadTester(long numIteration)
            {
                _numIteration = numIteration;
            }
     
            /*
             * Lance autant de thread que l'argument en paramètre.
             */
            public void LaunchThread(int numThread)
            {   
                Thread thread = null;
                _tic = DateTime.Now;
     
                while (numThread > 0)
                {
                    thread = new Thread(Treatment);
                    thread.Priority = ThreadPriority.Lowest ; // Pour que le thread traité par le processeur change le plus souvent possible.
                    thread.Start();
     
                    numThread--;
                }
            }
     
            /*
             * Methode qui sera lancé dans un thread et qui se charge de décrémenter _numIteration.
             */
            private void Treatment()
            {
                long done = 0; //Permet de compter le nombre de décrémentation.
                while ( _numIteration > 0 )
                {
                    // Je pense que c'est nécéssaire de mettre ici une zone critique mais je n'en suis pas sur à 100%
                    Thread.BeginCriticalRegion();
                    done++;
                    _numIteration--;
                    Thread.EndCriticalRegion();
                }
     
                Print(done);
            }
     
            /*
             * Imprime le délai de temps depuis le lancement de LaunchThread et le nombre de décrémentation.
             */
            private void Print(long done)
            {
                DateTime delay = new DateTime(DateTime.Now.Ticks - _tic.Ticks);
                Console.WriteLine(String.Format("{4}> {0}:{1}:{2} || done : {3}", delay.Minute, delay.Second, delay.Millisecond, done, Thread.CurrentThread.GetHashCode()));
            }
        }

  2. #2
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    292
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 292
    Par défaut
    réponse à 1)
    les 2 threads modifie le même entier au même moment. tout le contraire d'un traitement parallèle où tu pourrais espérer des gains de temps.

    si t'as un seul thread, il va mettre done et numIteration dans 2 registres sur 1 proc les incrémenter/décrementer et tu pourras pas faire plus rapide.

    imagine ton entier numIteration vaut 100
    il est dans un registre processeur
    tu veux le décrementer à 99

    ben soit tu fais une opération directement au niveau du proc !
    soit tu changes de contexte
    soit carrément tu dois prendre ton entier et l'envoyer à l'autre processeur !! et tu fais la même opération que t'aurait fait sur l'autre proc !!! intérêt ?

    d'ailleur l'essentiel de ton code se fait dans une region critique c a d que les 2 threads ne peuvent s'exécuter au même moment, ils doivent s'attendre mutuellement.

    si tu veux gagner du temps, au moment où tu lances tes thread, tu divises numIteration par le nombre de thread et chaque thread a son propre compteur numIteration. au final la somme des décrémentations sera bien le numIteration initial.

    pour le 2) j'ai pas compris. un truc doit m'échapper niveau c#

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    198
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 198
    Par défaut
    Un grand merci pour ta réponse clair et complète.
    Je vais re-tester tout ça

    Sinon pour la 2 (done != _numIteration initial), tu as des pistes que je pourrais explorer ?


    Merci

  4. #4
    Membre expérimenté
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Par défaut
    Citation Envoyé par AsPrO Voir le message
    Sinon pour la 2 (done != _numIteration initial), tu as des pistes que je pourrais explorer ?
    Si on reprend ton code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    while ( _numIteration > 0 )
    {
        Thread.BeginCriticalRegion();
        done++;
        _numIteration--;
        Thread.EndCriticalRegion();
    }
    Tu consommes _numIteration, qui est une variable commune à tous les threads, dans la condition de la boucle while. Tu modifies également cette variable au sein de la boucle while. Comme il n'y a pas de gestion sur l'exclusion mutuelle des threads (BeginCriticalRegion et EndCriticalRegion ne servent pas à ça) le problème est normal.

    Si on suppose que _numIteration vaut 1. Un thread arrive et rentre dans la boucle (car 1 > 0). Le thread arrive sur la ligne _numIteration-- est là, il passe la main à un autre thread qui arrive sur la boucle et rentre aussi (car _numIteration vaut toujours 1). Résultat on a plusieurs threads dans la boucle alors qu'on devrait en avoir un seul.

    L'exclusion mutuelle se fait au moyen de l'instruction lock.

    Par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    class ThreadTester
    {
        private static readonly object lockObject = new object();
     
        ...
     
        private void Treatment()
        {
            long done = 0;
     
            while (true)
            {
                lock (lockObkect)
                {
                    if (_numIteration <= 0) { break; }
                    _numIteration--;
                }
                done++;
            }
     
            Print(done);
        }
     
        ...
    }
    Un seul thread à la fois peut accèder à _numIteration de cette manière, évitant le problème soulevé précédemment.

Discussions similaires

  1. "pure method called" au test d'un wrapper boost::thread simple
    Par kidpaddle2 dans le forum Threads & Processus
    Réponses: 5
    Dernier message: 02/07/2010, 08h36
  2. Test d'un thread
    Par nadsky dans le forum Général Java
    Réponses: 5
    Dernier message: 22/05/2008, 14h16
  3. test unitaire d'une action qui lance un thread
    Par jawed84 dans le forum Struts 1
    Réponses: 1
    Dernier message: 29/02/2008, 17h12
  4. Teste si un thread existe déjà.
    Par ouranos21 dans le forum Concurrence et multi-thread
    Réponses: 6
    Dernier message: 15/01/2008, 14h41
  5. Réponses: 4
    Dernier message: 12/11/2005, 14h02

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo