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 :

Multi threading lent


Sujet :

C

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 11
    Points : 8
    Points
    8
    Par défaut Multi threading lent
    Bonjour,

    Je suis en train de découvrir les multithreads. J'ai donc récupérer un exemple de Intel :
    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
     
    #include <stdio.h>
    #include <pthread.h>
    #define INTERVALS 1000000000
    #define THREADS 2
    float global_sum = 0.0;
    pthread_mutex_t global_lock = PTHREAD_MUTEX_INITIALIZER;
    void *pi_calc (void *num);
    int main ()
    {
       pthread_t tid[THREADS];
       int i, t_num[THREADS];
       for (i = 0; i < THREADS; i++)
       {
          t_num[i] = i;
          pthread_create (&tid[i], NULL, pi_calc, &t_num[i]);
       }
       for (i = 0; i < THREADS; i++)
          pthread_join (tid[i], NULL);
       printf ("Pi = %f\n", global_sum);
    }
    void *pi_calc (void *num)
    {
       int i, myid, start, end;
       float h, x, my_sum = 0.0;
       myid = *(int *)num;
       h = 1.0 / INTERVALS;
       start = (INTERVALS / THREADS) * myid;
       end = start + (INTERVALS / THREADS);
       for (i = start; i < end; i++)
       {
          x = h * ((float)i - 0.5);
         my_sum += 4.0 / (1.0 + x * x);
      }
      pthread_mutex_lock (&global_lock);
         global_sum += my_sum;
      pthread_mutex_unlock (&global_lock);
    }
    Je compile sous linux (gcc main.c -o main -lpthread) et je teste les performances avec la commande time ./main : 29,01s user 0,00s system 198% cpu 14,611 total
    Le CPU travaille à 198% pendant 14.6 secondes : normal, processeur Dual Core.
    Afin de vérifier l'efficacité du Multithreading, je modifie le programme pour qu'il lance les 2 fonctions l'une après l'autre :
    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
     
    #include <stdio.h>
    #define INTERVALS 1000000000
    #define THREADS 2
    float global_sum = 0.0;
    void *pi_calc (void *num);
    int main ()
    {
       int i, t_num[THREADS];
       for (i = 0; i < THREADS; i++)
       {
          t_num[i] = i;
          pi_calc(&t_num[i]);
       }
       printf ("Pi = %f\n", global_sum);
    }
    void *pi_calc (void *num)
    {
       int i, myid, start, end;
       float h, x, my_sum = 0.0;
       myid = *(int *)num;
       h = 1.0 / INTERVALS;
       start = (INTERVALS / THREADS) * myid;
       end = start + (INTERVALS / THREADS);
       for (i = start; i < end; i++)
       {
          x = h * ((float)i - 0.5);
         my_sum += 4.0 / (1.0 + x * x);
      }
         global_sum += my_sum;
    }
    Je relance time : 14,49s user 0,00s system 99% cpu 14,490 total
    Le CPU travaille à 99% pendant 14.5 secondes.

    En fait, ce qui me perturbe c'est que la version multithread a la même vitesse d'exécution que la version utilisant un seul processeur. Normalement, la version multithread devrait être 2 fois plus rapide que l'autre.

    Est-ce que quelqu'un sait pourquoi il y a ce problème ?

    Merci

    Mr Bonheur

  2. #2
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par MrBonheur Voir le message
    En fait, ce qui me perturbe c'est que la version multithread a la même vitesse d'exécution que la version utilisant un seul processeur. Normalement, la version multithread devrait être 2 fois plus rapide que l'autre.
    Je suppose que le mutex 'resérialise' l'exécution...

    Fait tes calculs en 'double', la précision est meilleure (et le résultat plus cohérent...)

    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
     
    #include <stdio.h>
    #include <pthread.h>
     
    #define INTERVALS 1000000000
    #define THREADS 2
     
    double global_sum = 0.0;
    pthread_mutex_t global_lock = PTHREAD_MUTEX_INITIALIZER;
     
    static void *pi_calc (void *num)
    {
       int i, myid, start, end;
       double h, x, my_sum = 0.0;
       myid = *(int *) num;
       h = 1.0 / INTERVALS;
       start = (INTERVALS / THREADS) * myid;
       end = start + (INTERVALS / THREADS);
       for (i = start; i < end; i++)
       {
          x = h * ((double) i - 0.5);
          my_sum += 4.0 / (1.0 + x * x);
       }
       pthread_mutex_lock (&global_lock);
       global_sum += my_sum;
       pthread_mutex_unlock (&global_lock);
     
       return NULL;
    }
     
    int main (void)
    {
       pthread_t tid[THREADS];
       int i, t_num[THREADS];
       for (i = 0; i < THREADS; i++)
       {
          t_num[i] = i;
          pthread_create (&tid[i], NULL, pi_calc, &t_num[i]);
       }
       for (i = 0; i < THREADS; i++)
          pthread_join (tid[i], NULL);
       printf ("Pi = %f\n", global_sum);
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Pi = 3141592655.589901
    done in 31.109 s
     
    Press ENTER to continue.
    Pas de Wi-Fi à la maison : CPL

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 11
    Points : 8
    Points
    8
    Par défaut
    Je suppose que le mutex 'resérialise' l'exécution...
    C'est à dire ? je ne comprends pas.

    Même si je n'ai pas compris pourquoi la durée d'exécution est identique dans les 2 cas, j'ai essayé avec un autre exemple : un boucle pur sans paramètre ou calcul tordu et le résultat est plus que satisfaisant :

    Avec multithread :
    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
    #include <stdio.h>
    #include <pthread.h>
     
    #define THREADS 2
     
    pthread_mutex_t global_lock = PTHREAD_MUTEX_INITIALIZER;
     
    static void *calc ()
    {
       int i;
            double j = 0.;
            for (i=0;i<2000000000;i++)
            {
                    j = j + 1;
            }
       pthread_mutex_lock (&global_lock);
       pthread_mutex_unlock (&global_lock);
     
       return NULL;
    }
     
    int main (void)
    {
       pthread_t tid[THREADS];
       int i, t_num[THREADS];
       for (i = 0; i < THREADS; i++)
       {
          t_num[i] = i;
          pthread_create (&tid[i], NULL, calc, NULL);
       }
       for (i = 0; i < THREADS; i++)
          pthread_join (tid[i], NULL);
    }
    Durée : 37,01s user 0,00s system 193% cpu 19,112 total soit 19.1 secondes d'exécution.

    version sans thread :
    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
    #include <stdio.h>
    #include <pthread.h>
     
    #define THREADS 2
     
    pthread_mutex_t global_lock = PTHREAD_MUTEX_INITIALIZER;
     
    static void *calc ()
    {
       int i;
            double j = 0.;
            for (i=0;i<2000000000;i++)
            {
                    j = j+1;
            }
     
       return NULL;
    }
     
    int main (void)
    {
       pthread_t tid[THREADS];
       int i, t_num[THREADS];
       for (i = 0; i < THREADS; i++)
       {
          t_num[i] = i;
          calc();
       }
    }
    Durée : 35,13s user 0,00s system 99% cpu 35,160 total soit 35.2 secondes d'exécution.

    Par contre, je ne sais pas pourquoi, avec le précédent exemple, ça ne marche pas.

  4. #4
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par MrBonheur Voir le message
    Par contre, je ne sais pas pourquoi, avec le précédent exemple, ça ne marche pas.
    Parce que 2 processus en parallelle modifiants la même variable impliquent un mécanisme de synchronisation (mutex), qui a pour effet de ralentir l'action de chaque tâche (suspension le temps que l'écriture se termine). En définitive, on a effectué le même nombre de cycles d'écritures dans la variable commune. On a donc rien changé au temps total. (Ben oui, même avec 2 ou 50 processeurs, on peut pas écrire 'en même temps' dans la même variable. C'est ce que j'appelle la 'resérialisation...'
    Pas de Wi-Fi à la maison : CPL

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Tri multi-threadé
    Par Tifauv' dans le forum C
    Réponses: 8
    Dernier message: 28/06/2007, 09h00
  2. Réponses: 2
    Dernier message: 15/05/2004, 18h33
  3. Réponses: 16
    Dernier message: 30/01/2004, 11h05
  4. [VB6][active x] faire du multi-thread avec vb
    Par pecheur dans le forum VB 6 et antérieur
    Réponses: 9
    Dernier message: 20/05/2003, 12h01
  5. [Kylix] exception qtinft.dll et multi-threading
    Par leclaudio25 dans le forum EDI
    Réponses: 3
    Dernier message: 27/03/2003, 18h09

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