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

Threads & Processus C++ Discussion :

Questions de base sur le multithreading


Sujet :

Threads & Processus C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre chevronné
    Homme Profil pro
    Ingénieur 3D
    Inscrit en
    Avril 2008
    Messages
    400
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Ingénieur 3D

    Informations forums :
    Inscription : Avril 2008
    Messages : 400
    Par défaut Questions de base sur le multithreading
    Bonjour, je développe actuellement un programme de simulation physique qui se trouve être un poil trop lent à mon gout. J'ai donc pensé a paralléliser calcul en donnant une liste de primitives à chaque core. Le problème est que je n'ai bien evidemment jamais fait de multithreading avant.

    J'aimerai tout d'abord savoir si le multithreading vaut le coup car chaque thread risque de lire et écrire dans des variables utilisées par d'autres threads (et si je les bloque, je me retrouve avec les mêmes performances qu'un simple thread, non ?).
    Ensuite, d'après ce que j'ai pu lire, la bibliothèque boost ne permet pas de choisir sur quel core le thread sera exécuté. Faut-il donc impérativement passer par les commandes de windows ?

    Merci d'avance.

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Novembre 2008
    Messages : 31
    Par défaut
    Salut,
    Il est effectivement vrai que si deux threads écrivent dans la même variable ça peu poser problème, exemple :
    si tu lance 2 threads qui font l'action suivante :
    ++var;

    imaginons que var vaut initialement 0, les deux threads vont lire la variable, faire chaqu'un de son coté 0 + 1 = 1... puis ils vont tous les deux écrire 1 dans var...

    var sera donc égal à 1, et non pas 2...

    Sinon pour la question de quel thread sur quel core, j'ai toujours travailler avec plusieurs thread sous linux ou avec Qt. J'ai un quad-core et si je lance 4 threads, mes 4 cores tourne à 100%, jamais eu de soucis. Sauf erreur c'est toujours le système qui choisi que thread va sur quel coeur.

  3. #3
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Bonjour,
    Citation Envoyé par math_lab Voir le message
    J'aimerai tout d'abord savoir si le multithreading vaut le coup car chaque thread risque de lire et écrire dans des variables utilisées par d'autres threads (et si je les bloque, je me retrouve avec les mêmes performances qu'un simple thread, non ?).
    Ca peut dépendre de beaucoup de paramètres.
    D'abord si des données sont uniquement accédées en lecture et donc constantes tous le long de la simulation (typiquement, une géométrie), alors pas besoin de mettre en oeuvre un mécanisme de verrou pour gérer l'accès concurrent.
    Si des données sont écrites par un ou des threads avec des risques de race conditions, alors là effectivement, il faudra un mécanisme de contrôle de l'accès concurrent qui aura un coût. Mais cela peut être fait uniquement au moment de l'accès. Tu peux aussi regarder des patterns type reader/writer consumer/producer, etc.
    A la base, tu peux commencer par voir comment découper tes simulations pour minimiser ces éventuels conflits.

    Citation Envoyé par math_lab Voir le message
    Ensuite, d'après ce que j'ai pu lire, la bibliothèque boost ne permet pas de choisir sur quel core le thread sera exécuté. Faut-il donc impérativement passer par les commandes de windows ?
    Je ne sais pas si avec boost c'est possible. Peut être que d'autres bibliothèques le permettent ? Sinon, faudra passer par l'api windows...

  4. #4
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Citation Envoyé par math_lab Voir le message
    J'aimerai tout d'abord savoir si le multithreading vaut le coup car chaque thread risque de lire et écrire dans des variables utilisées par d'autres threads (et si je les bloque, je me retrouve avec les mêmes performances qu'un simple thread, non ?).
    De façon générale, passer en MT coûte plus de temps CPU que du monothread. Si tu préfères, tu gagnes du temps "réel" (humain, des heures / minutes / secondes), mais au prix de plus de ressources consommées (threads et objets de synchronisation) et plus de temps CPU.

    Pour t'expliquer brièvement : imagine un traitement qui se fait en une minute en monothread. Une fois en MT (deux threads), tu vas le faire en, disons, 35 secondes, c'est à dire proche du gain maximum possible.
    Or, si tu calcules le temps CPU consommé, tu vas arriver à 35 s X 2 (threads), donc ... 70 secondes ! Plus que les 60 initiales. Tu charges donc plus ta machine, même si (heureusement !) la plupart du temps ça ne gêne en rien car tu as largement plus de puissance disponible que tu n'en utilises.

    Donc, comme le précise 3DArchi, ça va dépendre de beaucoup de paramètres, et il n'y a pas de règle absolue. Certains traitements ne peuvent pas être parallélisés par nature (ex : calcul d'une série / suite mathématique), d'autres sont difficilement parallélisables (sous-entendu "en obtenant un gain significatif"), d'autres sont quasi-triviaux.

    Citation Envoyé par 3DArchi Voir le message
    Je ne sais pas si avec boost c'est possible. Peut être que d'autres bibliothèques le permettent ? Sinon, faudra passer par l'api windows...
    C'est une grosse lacune de beaucoup de librairies portables de gestion des threads : elles ne gèrent pas l'affinité processeur.
    Donc, direction l'API Windows pour ça. Pour ma part, je ne connais pas de librairie portable permettant de gérer l'affinité processeur, du moins dans les dernières versions que j'ai pu voir.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  5. #5
    Membre chevronné
    Homme Profil pro
    Ingénieur 3D
    Inscrit en
    Avril 2008
    Messages
    400
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Ingénieur 3D

    Informations forums :
    Inscription : Avril 2008
    Messages : 400
    Par défaut
    Merci pour vos réponses.
    Étant donné que ma fonction n'écrira dans les variables qu'à la fin du traitement, je pense que la synchro ne devrait pas être trop handicapante, et au pire, j'imagine que je peux même m'en passer en construisant un tableau temporaire qui stockerait les résultats et qui permettrait au programme principal de faire la mise à jour des variables.
    Sinon, je me rend bien compte que le multithreading a un certain cout et que le programme sera moins efficace, mais j'ai 8 cœurs a ma disposition, donc ce serait stupide de pas en tirer avantage.

    J'en profite d'ailleurs pour poser une autre question: doit-on créer et supprimer les threads à la volée quand on a besoin ? Je sais qu'avec join, on peut attendre la fin du thread, mais doit-il être détruit et reconstruit après pour pouvoir être re-exécuté ?

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par math_lab Voir le message
    doit-on créer et supprimer les threads à la volée quand on a besoin ?
    Lorsque on doit le faire souvent, alors on peut passer par un pool de threads.
    Ils sont créés en début de programme et se mettent en attente de boulot. Lorsque tu as un traitement, tu en prends un libre, tu l'actives en lui donnant le traitement à faire. Lorsqu'il a finit il revient dans le pool des threads dispo et s'endort (çad se met en attente d'un évènement pour un nouveau traitement).

  7. #7
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Dans un premier temps, regarde peut être OpenMP.

  8. #8
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Citation Envoyé par Mac LAK Voir le message
    C'est une grosse lacune de beaucoup de librairies portables de gestion des threads : elles ne gèrent pas l'affinité processeur.
    Donc, direction l'API Windows pour ça. Pour ma part, je ne connais pas de librairie portable permettant de gérer l'affinité processeur, du moins dans les dernières versions que j'ai pu voir.
    En quoi est-ce problématique quand il s'agit de faire du parallélisme pour les performances ?
    L'idée dans ce cas est de faire abstraction des primitive bas niveau et coûteuses comme les thread, les outils de lock au niveau du noyau,... et encore plus de l'affinité. Si tu règles l'affinité, comment fonctionnera le programme quand tu aura upgradé ta machine pour une avec 64 cœurs ?

    Côté bibliothèque, je conseillerais plus TBB d'Intel ou PPL de Microsoft que boost::thread pour ce genre d'usage. Elles fournissent des API permettant de s'abstraire de cette tuyauterie, et d'être plus efficace (notion de tâche plus légère qu'un thread, conteneur pour des échange de donnée multithread règlés finement en temre de minimisation des locks...).
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  9. #9
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    En quoi est-ce problématique quand il s'agit de faire du parallélisme pour les performances ?
    Parce que la charge n'est pas toujours idéalement répartie, tout simplement. Tu peux voir une illustration de ce problème sur ce vieux topic.

    En règle générale, dans le cas d'une optimisation maximale, tu en viens à être plus ou moins obligé de régler les affinités de façon à éviter la migration involontaire de threads, et/ou le regroupement de threads qui seraient soit "légers", soit non-concurrents.

    Mais pour faire ça, il faut avoir très bien compris ce que font chacun des threads de son application, et compris comment ils se synchronisent. Je te concède bien volontiers que ce n'est pas à la portée du premier débutant en parallélisme, et que ce n'est pas non plus un niveau d'optimisation requis pour toutes les applications.

    Citation Envoyé par JolyLoic Voir le message
    L'idée dans ce cas est de faire abstraction des primitive bas niveau et coûteuses comme les thread, les outils de lock au niveau du noyau,... et encore plus de l'affinité.
    C'est bien pour ça que j'utilise usuellement des API portables à ce sujet, qui sont d'ailleurs encore encapsulées dans des objets d'encore plus haut niveau de façon à simplifier tout ça au maximum... Tout en gardant une implémentation performante, car c'est souvent fait à base de templates et donc inliné un maximum.

    Et je continue donc de trouver très con de ne pas implémenter ces API d'affinités, quitte à les stubber sur les OS où cela pose problème... Tout le reste est implémenté, t'as même parfois des systèmes de priorité (inclus la modification du scheduling), et totalement portables, qui sont implémentés... L'affinité ne "coûtait" pas bien plus "cher" à ajouter.

    Citation Envoyé par JolyLoic Voir le message
    Si tu règles l'affinité, comment fonctionnera le programme quand tu aura upgradé ta machine pour une avec 64 cœurs ?
    Première règle d'une application gérant manuellement l'affinité : compter le nombre de cœurs / CPU disponibles réellement (= analyse du masque d'affinité du processus) en début d'application, et obtenir une map des coeurs/CPU utilisables.
    Ensuite, penser à utiliser cette map, avec les contraintes de répartition des threads requises par l'algo bien sûr, lors de la création de nouveaux threads.

    Je ne vois absolument pas où est le problème...
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  10. #10
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Citation Envoyé par Mac LAK Voir le message
    Parce que la charge n'est pas toujours idéalement répartie, tout simplement. Tu peux voir une illustration de ce problème sur ce vieux topic.
    J'ai parcouru ce topic, mais je n'ai rien vu qui permette de penser que tripatouiller l'affinité aurait améliorer quoi que ce soit en l'occurrence (par contre, un meilleur découpage des tâches avec une meilleure gestion de la mémoire, oui, probablement). Et j'ai envie de dire que, d'autant plus quand la charge n'est pas idéalement répartie, il vaut mieux laisser le système faire du task stealing, ce qui est incompatible avec une affinité gérée par le développeur
    Citation Envoyé par Mac LAK Voir le message

    En règle générale, dans le cas d'une optimisation maximale, tu en viens à être plus ou moins obligé de régler les affinités de façon à éviter la migration involontaire de threads, et/ou le regroupement de threads qui seraient soit "légers", soit non-concurrents.
    Sauf que le système de tâche placé au dessus des threads est déjà fait pour ça, normalement, et j'ai l'impression que c'est le genre de chose qui peut se gérer automatiquement mieux qu'à la main (sauf éventuellement si la main est celle d'un véritable génie), tout comme à une époque l'attribution des registres était une activité normale d'optimisation, alors que maintenant on laisse faire le compilateur. Tout ce que l'utilisateur a à faire est de fournir un découpage avec la bonne granularité (ni trop, ni trop peu), qui respecte bien l'agencement mémoire (des données devant être touchées par deux tâches différentes doivent être physiquement loin les unes des autres, et inversement), et qui minimise les synchronisations nécessaires (dans l'idéal, aucune). A partir de là (ce qui est déjà beaucoup demander), au système de se débrouiller.
    C'est d'autant plus vrai hors du monde embarqué, où l'on ne maîtrise par tout ce qui tourne sur la machine et où une optimisation manuelle fine risque de devenir une vraie pessimisation pour peu qu'un autre programme tourne derrière, et fasse lui aussi beaucoup de calculs.
    Citation Envoyé par Mac LAK Voir le message
    Mais pour faire ça, il faut avoir très bien compris ce que font chacun des threads de son application, et compris comment ils se synchronisent. Je te concède bien volontiers que ce n'est pas à la portée du premier débutant en parallélisme, et que ce n'est pas non plus un niveau d'optimisation requis pour toutes les applications.
    J'ai l'impression que c'est aussi inutile, voire néfaste, dans la très grande majorité des cas. As-tu un cas réel ou ça a eu un impact en tête (attention, je ne parle pas de parallélisme pour répondre à un évènement rapidement, là l'affinité peut avoir de l'intérêt, mais du parallélisme pour calculer vite) ?
    Citation Envoyé par Mac LAK Voir le message
    L'affinité ne "coûtait" pas bien plus "cher" à ajouter.
    Je ne sais pas trop de quel système tu parles, mais dans ceux que je connais un peu (TBB et PPL), j'ai l'impression que ne pas exposer l'affinité n'est pas un manque, mais une décision consciente visant à "obliger" les développeurs à prendre de la distance par rapport au système.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

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

Discussions similaires

  1. Réponses: 13
    Dernier message: 10/10/2007, 10h09
  2. [Débutant] Questions de base sur java
    Par JajaY dans le forum Langage
    Réponses: 2
    Dernier message: 04/04/2006, 18h51
  3. Question de base sur l'utilisation de la fonction date()
    Par deaven dans le forum Langage SQL
    Réponses: 2
    Dernier message: 04/12/2005, 15h33
  4. Question de base sur les classes
    Par deaven dans le forum C++
    Réponses: 3
    Dernier message: 27/11/2005, 16h20
  5. [Débutant] Question de base sur le BDE et les SGBD
    Par Invité dans le forum Bases de données
    Réponses: 3
    Dernier message: 15/03/2005, 08h45

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