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 :

questions sur les threads


Sujet :

C

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Janvier 2012
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2012
    Messages : 6
    Par défaut questions sur les threads
    Bonjour,
    j'essaye de diviser mon programme en 4 thread car j'ai un processeur à 4 coeur. Mon programme est il censé s’exécuter 4 fois plus rapidement que si je ne gère pas les thread ?
    J'ai essayé ce code :
    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
    #include <stdio.h>
    #include <pthread.h>
     
    #if defined (Win32)
    #  include <windows.h>
    #  define psleep(sec) Sleep ((sec) * 1000)
    #elif defined (Linux)
    #  include <unistd.h>
    #  define psleep(sec) sleep ((sec))
    #endif
     
    static void * funct(void * data);
     
    void main()
    {
    	int ret = 0;
    	unsigned long id1 = 1;
    	unsigned long id2 = 2;
    	unsigned long id3 = 3;
    	unsigned long id4 = 4;
    	unsigned long debut1 = 0;
    	unsigned long debut2 = 1250001;
    	unsigned long debut3 = 2500001;
    	unsigned long debut4 = 3750001;
     
    	ret = pthread_create (&id1, NULL, funct, (void *) debut1);
    	ret = pthread_create (&id2, NULL, funct, (void *) debut2);
    	ret = pthread_create (&id3, NULL, funct, (void *) debut3);
    	ret = pthread_create (&id4, NULL, funct, (void *) debut4);
     
    	pthread_join (id1, NULL);
    	pthread_join (id2, NULL);
    	pthread_join (id3, NULL);
    	pthread_join (id4, NULL);
     
    }
     
    static void * funct(void * data)
    {
    	unsigned long i;
    	unsigned long debut = (unsigned long) data;
     
     
     
    	for (i = debut ; i < debut+1250000 ; i++)
    		printf("%lu\n", i);
     
    	return NULL;
    }
    Pourtant cela s’exécute un peu plus lentement que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #include <stdio.h>
     
    void main()
    {
    	unsigned long i = 0;
    	for (i = 0 ; i < 5000000 ; i++)
    		printf("%lu\n",i);
    }
    Et quand je regarde l'utilisation de mes cpu avec "Surveillance du système" de KDE, je n'ai qu'un seul cpu à 100% et les autres aux alentours de 50%.
    Comment faire pour utiliser tous mes cpu à 100% ? Est ce quelque chose à régler dans le système d'exploitation ou dans mon programme ?
    Et au passage une petite explication rapide (si c'est possible) pour comprendre pourquoi le temps d’exécution passe d'environ 3 secondes à 27 seconde si je met un \n dans mon printf ?

    Merci d'avance

  2. #2
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    salut,

    Citation Envoyé par Shugen Voir le message
    Mon programme est il censé s’exécuter 4 fois plus rapidement que si je ne gère pas les thread ?
    non, le propos des threads c'est de paralléliser des traitement, pas d'aller plus vite, le fait qu'un programme se déroule plus vite grâce aux threads dépend entièrement de la façon de programmer

    J'ai essayé ce code (...) cela s’exécute un peu plus lentement que (...)
    ça n'est pas pertinent du tout, ce qui prend le plus de temps c'est printf, faudrait voir ce qui crée un écart réel, peut-être que la mesure est faussée aussi etc.

    Comment faire pour utiliser tous mes cpu à 100% ? Est ce quelque chose à régler dans le système d'exploitation ou dans mon programme ?
    c'est le job du noyau de gérer la répartition des processus sur les différents CPU, sous-entendu on gagne souvent à lui faire confiance il connait son boulot, notamment il me semble que la balance des processus d'une workqueue à l'autre cherche à optimiser l'efficacité des caches CPU, au delà il est possible de forcer l'affinité d'un processus en mode utilisateur à travers sched_setaffinity(2)

    pourquoi le temps d’exécution passe d'environ 3 secondes à 27 seconde si je met un \n dans mon printf ?
    je dirais que c'est à cause/grâce au buffering réalisé par la libc, à valider néanmoins

  3. #3
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    En effet, ton programme test illustre assez bien toutes les difficultés de la programmation parallèle...

    1. je sais bien que ce n'est qu'un exemple de test, mais utiliser printf dans la fonction parallélisée c'est choisir de partager une ressource "l'affichage console" entre 4 threads qui vont y accéder sans se consulter... d'où la probabilité d'affichages bizarres et l'impossibilité de déterminer l'ordre dans lequel il se fera.

    2. quand une ressource est partagée (en particulier une ressource physique, comme l'écran), un goulet d'étranglement se forme qui enlève une partie, voire l'intégralité du gain de temps du multithreading

    3. la création et la destruction de thread n'est en rien gratuite. En l'occurrence, le nombre de données que tu utilises est grand et ce serait rentabilisé (si les calculs étaient importants; encore une fois, c'est printf qui prend toute la place et accède à une ressource unique qui ne peut être réellement partagée).

    4. pour l'ajout de '\n' qui augmente le temps d'exécution, je pense que c'est à cause du modèle graphique de la console, ce n'est pas lié au parallélisme, le rafraîchissement y est toujours très lent et il y en a beaucoup plus lorsque tu sautes une ligne à chaque nombre

    5. les bases du multithreading sont les suivantes:
    - ne paralléliser que ce qui le mérite vraiment (après avoir profilé son code)
    - ne paralléliser que ce qui peut être parallélisé (si l'ordre dans lequel le code est exécuté est important, il arrive qu'on ne puisse pas paralléliser)
    - isoler les parties du code parallélisées des autres

  4. #4
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Janvier 2012
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2012
    Messages : 6
    Par défaut
    Merci pour vos éclaircissements.
    C'était vraiment pas une bonne idée de test alors xD.
    Quel est l'avantage de paralléliser des traitements à part aller plus vite ?
    N'est il pas possible d'allouer une grosse partie des ressources de tous les cpu pour l’exécution d'un programme ?
    En fait dans mon programme réel, je fais uniquement des calculs à partir des données de fichiers et j'enregistre les résultats dans une BDD. La gestion multi thread devrait accélérer l’exécution alors, non?
    Pour le \n, effectivement, en redirigeant la sortie vers un fichier l’exécution est beaucoup plus rapide.

  5. #5
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    printf() est une fonction lente et tous tes threads vont utiliser la même ressource, même s'ils tournent sur des cœurs différents.

    Tu peux avoir un traitement bloquant (par exemple, attendre la saisie au clavier de l'utilisateur) et faire des calculs en arrière-plan avec des threads.

    Dans ton cas de programme, il est très probable que des threads te permettent d'aller plus vite. Après, ça se gère aussi au niveau de l'OS car au final c'est lui qui alloue des cœurs et du temps CPU à ton programme.

  6. #6
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    Citation Envoyé par Shugen Voir le message
    Quel est l'avantage de paralléliser des traitements à part aller plus vite ?
    On distingue parfois programmation parallèle et concurrente:
    parallèle: exécution en parallèle de plusieurs parties d'un calcul pour le réaliser plus rapidement
    concurrente: répartition dans différents threads de parties séparées d'une application

    Par exemple: on peut paralléliser l'addition des éléments d'un grand tableau (dans le style de ton exemple) / attribuer des threads à l'interface graphique, la partie métier, aux accès à une base de donnée

    Citation Envoyé par Shugen Voir le message
    En fait dans mon programme réel, je fais uniquement des calculs à partir des données de fichiers et j'enregistre les résultats dans une BDD. La gestion multi thread devrait accélérer l’exécution alors, non?
    Là tu as trois parties: l'ouverture / lecture des données dans les fichiers, les calculs, la sauvegarde dans la bdd. La partie la plus aisée à paralléliser est celle du milieu (selon la nature de l'opération à effectuer).

  7. #7
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 150
    Par défaut
    Citation Envoyé par Shugen Voir le message
    En fait dans mon programme réel, je fais uniquement des calculs à partir des données de fichiers et j'enregistre les résultats dans une BDD. La gestion multi thread devrait accélérer l’exécution alors, non?
    La lecture de données dans un fichier peut-elle gagner à être faite en parallèle ?
    Oui, dans certains cas précis.
    Non dans la plupart des cas.

    Exemple facile : tu as un (gros) fichier, stocké sur disque. Que va-t-il se passer si N threads demandent en même temps de lire différentes parties du fichier ? Le disque va commencer à servir le premier thread, puis va s'interrompre pour aller lire un autre secteur pour servir le second et ainsi de suite, avant de retourner lire le premier secteur pour resservir le premier thread... Moins performant qu'une lecture simple.
    Maintenant, si tu as une configuration RAID qui réplique ton fichier, et que chaque thread peut être servi par un disque différent, tu peux en théorie accélérer la lecture.

    Etc, avec tous les cas que tu peux imaginer

    calculs : certains se parallélisent bien, d'autres pas, c'est super dépendant.
    Par exemple initialiser chaque case d'un tableau avec la valeur de la cellule précédente plus un, ça peut s'écrire comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    tab[0] = VALEUR_INITIALE;
    for (i=1 ; i < MAX ; i++)
       tab[i] = tab[i-1]
    Qui se parallélise très mal sans ré-écrire l'algo, ou bien comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for (i=0 ; i < MAX ; i++)
      tab[i] = VALEUR_INITIALE + i;
    qui se parallélise très bien, car tu peux facilement couper le calcul de 0 à N-1, de N à 2N-1, de 2N à 3N-1, ...

    Et enfin l'accès concurrent à la base de données : est-ce que tu utilises Oracle, MySQL ou SQLite ? Dans le premier cas, la gestion des accès concurrent est bien prévue, pour peu que tes N threads ne cherchent pas à accéder tous aux mêmes enregistrements de la même table du même schéma.
    Dans le dernier cas, tu gagnerais peut-être du temps à passer à un vrai SGBD
    "La route est longue, mais le chemin est libre" -- https://framasoft.org/
    Les règles du forum

Discussions similaires

  1. Question sur les threads
    Par thebloodyman dans le forum Concurrence et multi-thread
    Réponses: 3
    Dernier message: 22/01/2007, 07h28
  2. Questions sur les threads: généralités
    Par Gragra dans le forum C++
    Réponses: 9
    Dernier message: 04/11/2006, 16h28
  3. Quelques questions sur les threads
    Par benj63 dans le forum C++Builder
    Réponses: 28
    Dernier message: 21/11/2005, 13h27
  4. Question sur les threads
    Par Linio dans le forum Concurrence et multi-thread
    Réponses: 10
    Dernier message: 21/10/2005, 09h08
  5. Question sur les threads
    Par nicolas66 dans le forum MFC
    Réponses: 4
    Dernier message: 03/06/2005, 20h57

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