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

Linux Discussion :

utilisation de pthread en C


Sujet :

Linux

  1. #1
    Candidat au Club
    Homme Profil pro
    Développeur C++/Delphi
    Inscrit en
    Février 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C++/Delphi

    Informations forums :
    Inscription : Février 2012
    Messages : 7
    Points : 3
    Points
    3
    Par défaut utilisation de pthread en C
    Bonjour,

    J'espère que je suis dans la bonne rubrique du forum.

    Je cherche à parallèliser une application à l'aide de threads. Je souhaite définir un nombre de processus pouvant tourner en parallèle et découper automatiquement mon application en fonction de ce nombre.

    Pour cela j'ai voulu tester le code suivant sur un exemple simple:

    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
     
    #include "stdio.h"
    #include "math.h"
    #include "time.h"
    #include "pthread.h"
    #include "stdlib.h"
     
    #define nPE 4        /*nombre de processeur*/
     
     
    void* mafonction(void* p_data)
    {
    int i;
    int cpt=0;
     
    for(i=0;i<10000;i++)
        {cpt++;}
     
    return NULL;
    }
     
    int main()
    {
    pthread_t thread[nPE-1];
    int i;
    int num_thread;
     
    num_thread=0;
     
    for(i=0;i<30;i++)
    {
        while(pthread_create(&thread[num_thread],NULL,mafonction,NULL)!=0)
           {num_thread=(num_thread+1)%(nPE-1);}
           num_thread=(num_thread+1)%(nPE-1);
    }
    return 0;
    }
    Je souhaitais que la boucle while crée les processus automatiquement jusqu'à ce que les nPE-1 threads soient utilisés. Une fois tous les thread utilisés, elle parcours la boucle while jusqu'à ce qu'elle trouve un thread libéré pour le réutiliser.
    Pour cela je me suis basé sur l'hypothèse que la fonction pthread_create renverait une valeur non nulle si le thread existait déjà. Il semblerait que ça ne soit pas le cas.

    En débug j'obtiens les résultats suivant:
    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
     
    [Thread debugging using libthread_db enabled]
    [New Thread 0xb7e2cb70 (LWP 2014)]
    [New Thread 0xb762bb70 (LWP 2015)]
    [Thread 0xb7e2cb70 (LWP 2014) exited]
    [New Thread 0xb6e2ab70 (LWP 2016)]
    [Thread 0xb762bb70 (LWP 2015) exited]
    [New Thread 0xb6629b70 (LWP 2017)]
    [Thread 0xb6e2ab70 (LWP 2016) exited]
    [New Thread 0xb5e28b70 (LWP 2018)]
    [Thread 0xb6629b70 (LWP 2017) exited]
    [Thread 0xb5e28b70 (LWP 2018) exited]
    [New Thread 0xb5627b70 (LWP 2019)]
    [New Thread 0xb4e26b70 (LWP 2020)]
    [New Thread 0xb4625b70 (LWP 2021)]
    [New Thread 0xb3e24b70 (LWP 2022)]
    [Thread 0xb5627b70 (LWP 2019) exited]
    [Thread 0xb4e26b70 (LWP 2020) exited]
    [New Thread 0xb3623b70 (LWP 2023)]
    [New Thread 0xb2e22b70 (LWP 2024)]
    [New Thread 0xb2621b70 (LWP 2025)]
    On constate que je me retrouve avec plus de 5 threads à certains moments de l'exécution alors que je pensais les avoir limité à 3.

    J'attend vos suggestions pour résoudre ce problème et me proposer des solutions pour découper cette application en nPE-1 threads.

    J'ai aussi tenté d'utiliser ce genre d'instructions toutes les nPe-1 créations de thread pour résoudre le problème:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    for (i=0;i<nPE-1;i++)
    {
    pthread_join(thread[j],NULL);
    }
    Cette instruction devait avoir pour but d'attendre la fin des threads créés pour ensuite les réutiliser.

    Il semblerait donc que je puisse créer plus de thread que ce que j'ai déclaré...
    Je ne parviens pas non plus à attendre la fin de leur exécution...

    Merci d'avance pour votre aide.

  2. #2
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 860
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 860
    Points : 219 064
    Points
    219 064
    Billets dans le blog
    120
    Par défaut
    Bonjour,

    Pour la fonction pthread_create() la valeur de retour indique s'il y a eu une erreur. Il faut savoir qu'un système peut exécuter un nombre important de threads, même si celui n'a qu'un CPU avec un coeur unique. Derrière, c'est le système qui va gérer l'ordonnancement des threads et dire lequel doit être exécuté à quel moment.

    Pour la fonction pthread_join(), lors de l'appel de celle-ci le thread appelant se bloquera et attendra la fin du thread renseigné. Ce qui veut dire que dans votre boucle, il faudra que le premier thread finisse, pour enfin attendre le second (qui peut lui même être fini avant le premier, et donc ne pas bloqué plus que ça l'execution de la boucle).

    Pour revenir à vos problèmes. J'ai envie de dire, avez vous regarder du coté de OpenMP ?

    Sinon, ce que vous souhaitez faire ressemble beaucoup à une piscine de threads (thread_pool). Il y a une de disponible dans Boost, ce sera toujours plus simple d'utiliser celle-ci.

    Finalement, je ne sais pas comment connaitre le nombre de threads optimale avec pthreads. Disons que dans GCC, la règle est NbCoeurs + 1. Mais nous passons l'information en ligne de commande. C'est pour cela que j'imagine que vous devez utiliser un système similaire (ou avec une variable constante).

    Pour en finir,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for (i=0;i<nPE-1;i++)
    {
    pthread_join(thread[j],NULL);
    }
    Si c'est pour faire en sorte de relancer les threads une fois finalisé, alors, je vous conseille un while(1) (ou un while tant que la travail complet n'est pas fini) et dedans vous mettez un : pthread_try_join() qui regardera si le thread est fini (s'il ne l'ai pas, vous passez au suivant).
    Il faudra aussi penser à donner un peu de répits au thread principal sinon, vous allez utilisé 100% du CPU à juste regarder si les autres threads sont terminés.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  3. #3
    Candidat au Club
    Homme Profil pro
    Développeur C++/Delphi
    Inscrit en
    Février 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C++/Delphi

    Informations forums :
    Inscription : Février 2012
    Messages : 7
    Points : 3
    Points
    3
    Par défaut
    Merci pour votre aide.

    Je pense effectivement que la fonction pthread_try_join() sera mieux appropriée à mon utilisation.

    Je pensais que la déclaration pthread_t thread[nPE-1]; fixait le nombre de thread, il semblerait que je me trompe.
    On peut créer deux threads différents avec pthread_create en passant le même pthread_t en paramètre?

    J'aimerais pouvoir imposer le nombre de threads utilisés, de préférence en définissant une constante dans le programme. Vous disiez que cela était possible en ligne de commande avec GCC, si oui, pourriez vous m'indiquer comment.

    Merci.

  4. #4
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 860
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 860
    Points : 219 064
    Points
    219 064
    Billets dans le blog
    120
    Par défaut
    La seule chose qui limite le nombre de threads c'est vous (et la machine, mais c'est un peu plus rare).
    Si vous voulez N threads, vous pouvez faire de la sorte :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    const unsigned int N = 10;
     
    for ( int i = 0 ; i < N ; i++ )
    {
         thread_create(...);
    }
    Pour récupérer les informations passées en ligne de commande, on utilise les variables argc / argv paramètres de la fonction main()
    Sinon, vous pouvez utiliser la fonction getopt() qui fait beaucoup de choses pour nous .
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  5. #5
    Candidat au Club
    Homme Profil pro
    Développeur C++/Delphi
    Inscrit en
    Février 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C++/Delphi

    Informations forums :
    Inscription : Février 2012
    Messages : 7
    Points : 3
    Points
    3
    Par défaut
    j'ai essayé d'utiliser pthread_tryjoin_np pour déterminer si le thread numéo: num_thread est libre ou non.

    Cette fonction doit retourner une valuer non nulle si le thread s'exécute encore. J'ai donc pensé utiliser le code suivant:

    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
     
    int main()
    {
    pthread_t thread[nPE-1];
    int i;
    int num_thread;
    num_thread=0;
    void **retval=NULL;
     
    for(i=0;i<30;i++)
    {
     
    	while(pthread_tryjoin_np(thread[num_thread],retval)!=0)
    	{
    	num_thread=(num_thread+1)%(nPE-1);
    	}
    	pthread_create(&thread[num_thread],NULL,mafonction,NULL);
    	num_thread=(num_thread+1)%(nPE-1);
    }
    return 0;
    }
    Le but est d'utiliser le premier thread libre qui se présente quand les autres sont utilisés. Donc si on trouve que le thread[num_thread] est en fonctionnement, on passe au suivant ainsi de suite.

    A la compilation j'ai l'avertissement suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    test2.c: In function ‘main’:
    test2.c:35:2: warning: implicit declaration of function ‘pthread_tryjoin_np’
    Et à l'exécution je pars tout de suite en boucle infini sur while(pthread_tryjoin_np(thread[num_thread],retval)!=0)

    Je me suis dis qu'il pouvait y avoir d'autres erreurs que celles indiquant que le thread n'est pas terminé j'ai donc voulu utiliser la constante EBUSY mais il ne la trouve pas.

  6. #6
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 860
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 860
    Points : 219 064
    Points
    219 064
    Billets dans le blog
    120
    Par défaut
    Pour le warning, il semble que vous ayez oublié d'inclure le fichier d'entête #include <pthread.h>Sinon pour votre code, je pensais plus à quelque chose comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    while ( 1 )
    {
         if ( pthread_tryjoin_np(thread[num_thread],retval) != 0 )
        {
    	pthread_create(&thread[i],NULL,mafonction,NULL);
        }
    }
    Enfin, c'est un mélange de pseudo code
    Sinon, le while(1) est dégoutant, et il faut le remplacer par un test réel sur si le travail est fini.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

Discussions similaires

  1. Conseil utilisation de la lib GNU pthread
    Par morpheusmg dans le forum Débuter
    Réponses: 5
    Dernier message: 09/01/2013, 13h50
  2. Utilisation de la bibliothèque pthread
    Par Emmanuel Delahaye dans le forum C
    Réponses: 0
    Dernier message: 01/09/2010, 17h54
  3. Utilisation de pthread et structure
    Par Nieli dans le forum C
    Réponses: 1
    Dernier message: 10/10/2008, 20h47
  4. utilisation d'un timer avec les pthreads
    Par dc.sara dans le forum C
    Réponses: 8
    Dernier message: 15/01/2008, 13h12
  5. [Visual C++] Utilisation de pthread
    Par Stupeflip dans le forum Windows
    Réponses: 4
    Dernier message: 23/02/2007, 14h36

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