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 :

[C++ / TBB] Récupérer un ID unique pour un parallel_for


Sujet :

C++

  1. #1
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut [C++ / TBB] Récupérer un ID unique pour un parallel_for
    Bonjour,

    Je découvre la librairie TBB d'Intel pour la programmation multi-threading. J'ai bien compris comment fonctionne la fonction parallel_for mais je souhaiterais savoir s'il est possible de récupérer un ID unique pour chaque thread qui appelle la lambda ? J'ai vu qu'on pouvait récupérer l'ID du thread mais en fait je veux un ID compris entre 0 et nbThread.

    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
     
    static int id;
    id = 0;
    unsigned int nbThread = 4;
    unsigned int workPerThreadAjust = NodesToAnalyse.size()/nbThread+1;
    tbb::parallel_for( tbb::blocked_range<size_t>(0, NodesToAnalyse.size(), workPerThreadAjust),
    	[&](const tbb::blocked_range<size_t>& r) {
    		s_mutex.lock();
    		std::cout << "Thread ID=" << id << " / Analyse range: " << r.begin() << " -> " << r.end();
    		++id;
    		s_mutex.unlock();
     
    		this->_analyseNode(NodesToAnalyse, r.begin(), r.end(), id-1);
     
    	} // fin de la lambda
    )
    Alors cette solution avec une variable statique pour l'id et un mutex fonctionne très bien mais je trouve que c'est sale et puis cela necessite une synchronisation donc une perte de performance.

    La fonction tbb::this_tbb_thread::get_id() ne fonctionne pas car retourne un gros identifiant (celui du thread courant) mais qui n'est pas dans l'intervalle [0, nbThread[

    Une idée ?

    Merci par avance
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  2. #2
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Je ne connais pas cette bibliothèque mais ta solution est tout à fait acceptable. On se fout un peu des conséquences de la synchronisation vu que la section critique est exécutée une seule fois et se trouve en dehors du traitement proprement dit.

  3. #3
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut
    Bonsoir,

    Non justement la section critique n'est pas exécutée une seule fois :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    s_mutex.lock();
    		std::cout << "Thread ID=" << id << " / Analyse range: " << r.begin() << " -> " << r.end();
    		++id;
    		s_mutex.unlock();
    Ce code la est appelé X fois en fonction de la granularité demandée pour la boucle for donc de workPerThread dans mon exemple.
    Dans mon projet, il se peut que ce soit appelé des milliers de fois d'où mon problème avec le mutex...

    Je suis presque sur qu'il existe une solution clean sans mutex mais je ne trouve rien sur internet sur TBB qui n'est pas super bien documenté (à mon sens )
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  4. #4
    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 : 49
    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
    Points : 16 213
    Points
    16 213
    Par défaut
    Je ne connais pas TBB en pratique, mais si ton NodeToAnalyze est accessible en random access, je ferais un parallel_for sur des entiers de 0 à NodeToAnalyze.size(), et dans la lambda, j'accèderais à NodeToAnalyze[i].

    Mais sinon, ton besoin d'identifiant unique me semble louche...
    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.

  5. #5
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Citation Envoyé par Aspic Voir le message
    Ce code la est appelé X fois en fonction de la granularité demandée pour la boucle for donc de workPerThread dans mon exemple.
    Puis-je en déduire alors que cette méthode ne fonctionne pas, puisque ton identifiant va être incrémenté plusieurs fois pour chaque thread ?


    Citation Envoyé par Aspic Voir le message
    Je suis presque sur qu'il existe une solution clean sans mutex mais je ne trouve rien sur internet sur TBB qui n'est pas super bien documenté (à mon sens )
    La seule manière de faire ça sans synchronisation serait d'avoir assez de contrôle sur le thread pour l'initialiser avec l'identifiant, ce qui n'est pas forcément le cas avec un parallel for (à voir si la bibliothèque le permet). Une fois le thread lancé c'est bien entendu impossible.

  6. #6
    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 : 49
    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
    Points : 16 213
    Points
    16 213
    Par défaut
    En lisant la réponse de Matt_Houston, je me dis que j'ai peut-être mal compris la question : Est-ce que tu veux un identifiant par tâche lancée (donc si ta boucle a n éléments, n ids différents), ou bien un identifiant par thread sous-jacent qui fait tourner la boucle (donc probablement environ 1 id par core de l'environnement d'exécution). La formulation de ta question me fait penser au 2, mais ta proposition de solution me fait penser au 1...
    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.

  7. #7
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    Je ne connais pas TBB en pratique, mais si ton NodeToAnalyze est accessible en random access, je ferais un parallel_for sur des entiers de 0 à NodeToAnalyze.size(), et dans la lambda, j'accèderais à NodeToAnalyze[i].

    Mais sinon, ton besoin d'identifiant unique me semble louche...
    C'est exactement ce que je fais mais l'ID unique me sert pour d'autres ressources partagées entre les threads et grâce à ce ID unique, je n'ai pas besoin de mutex...

    Donc pour répondre à ta question, je souhaite un ID unique par tâche lancée, c'est à dire à chaque appel de la lambda. Grâce à TBB, je peux contrôler le nombre de fois que je lance la lambda avec le 3ème paramètre :
    tbb::parallel_for( tbb::blocked_range<size_t>(0, NodesToAnalyse.size(), workPerThreadAjust)

    Puis-je en déduire alors que cette méthode ne fonctionne pas, puisque ton identifiant va être incrémenté plusieurs fois pour chaque thread ?
    Si si ca marche très bien, testé en mettant du debug dans la lambda :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    s_mutex.lock();
    		std::cout << "Thread ID=" << id << " / Analyse range: " << r.begin() << " -> " << r.end();
    		++id;
    		s_mutex.unlock();
    Si j'utilise 8 threads, j'ai bien 8 appels et donc 8 ID uniques dans l'intervalle [0, 8[
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Vue la spécificité du besoin, je doute que tu puisses avoir mieux.
    Un tel identifiant de thread n'a aucun sens au sens du thread, il s'agit d'un index de tableau spécifique à ton utilisation des threads, quand bien même cette utilisation est faîte via TBB, rien n'assure que lui utilisera un tableau en interne pour les ranger.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  9. #9
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Vue la spécificité du besoin, je doute que tu puisses avoir mieux.
    Un tel identifiant de thread n'a aucun sens au sens du thread, il s'agit d'un index de tableau spécifique à ton utilisation des threads, quand bien même cette utilisation est faîte via TBB, rien n'assure que lui utilisera un tableau en interne pour les ranger.
    Oui possible que ce soit trop spécifique, enfin c'est pas très grave non plus, ma solution fonctionne bien mais peut être que c'est la conception qui n'est pas top

    Merci en tout cas
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  10. #10
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    La seule option pour ne pas avoir de lock serait d'utiliser un intrinsic d'incrémentation, par exemple sous VS https://msdn.microsoft.com/en-us/library/2ddez55b.aspx
    Peut-être que std::atomic peut être utilisé aussi, mais ça dépendra de l'implémentation je pense.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  11. #11
    Membre confirmé
    Avatar de gb_68
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2006
    Messages
    232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 232
    Points : 546
    Points
    546
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    	[&](const tbb::blocked_range<size_t>& r) {
    		s_mutex.lock();
    		std::cout << "Thread ID=" << id << " / Analyse range: " << r.begin() << " -> " << r.end();
    		++id;
    		s_mutex.unlock();
    		
    		this->_analyseNode(NodesToAnalyse, r.begin(), r.end(), id-1);
    	 
    	} // fin de la lambda
    Attention tu utilises ton id en dehors de tout mutex !
    Après le unlock un autre thread peut très bien l'avoir déjà remodifier.

    En multi-threading il vaut mieux travailler le plus possible avec des données propres à chaque thread et faire le moins souvent appel à des données partagés (à moins qu'elles ne soient en lecture seule).

    Exemple avec une copie locale de l'id :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    	[&](const tbb::blocked_range<size_t>& r) {
    		int current_id;
                    s_mutex.lock();
                    current_id = id++;
    		std::cout << "Thread ID=" << current_id << " / Analyse range: " << r.begin() << " -> " << r.end();		
    		s_mutex.unlock();
     
    		this->_analyseNode(NodesToAnalyse, r.begin(), r.end(), current_id);
     
    	} // fin de la lambda
    Pour te passer des mutex, tu peux aussi regarder du côté des atomic (je ne connais pas ttb, mais apparemment cette bibliothèque en possèdent aussi). [Edit] Grillé par Bousk

  12. #12
    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 : 49
    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
    Points : 16 213
    Points
    16 213
    Par défaut
    Et qu'est-ce qui ne correspond pas dans ma première proposition ?
    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.

Discussions similaires

  1. [C#] Format unique pour les mêmes affichages ?
    Par luimême dans le forum ASP.NET
    Réponses: 3
    Dernier message: 22/11/2005, 17h32
  2. Y a t il un format unique pour les hd portables
    Par von_magnus dans le forum Composants
    Réponses: 6
    Dernier message: 27/09/2005, 18h38
  3. Réponses: 2
    Dernier message: 13/08/2004, 16h50
  4. Réponses: 3
    Dernier message: 23/01/2004, 21h02

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