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 c++


Sujet :

C++

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    338
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 338
    Points : 0
    Points
    0
    Par défaut multi threading c++
    Bonjour, J'ai fais un programme pour la lecture des graphes à partir d'un fichier:
    Code x : 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
    t # 0
    v 0 0
    v 1 3
    v 2 9
    e 2 1 68
    e 0 1 10
    e 0 2 4
    t # 1
    v 0 2
    v 1 11
    v 2 6
    v 3 10
    v 4 18
    v 5 14
    e 0 1 15
    e 2 5 19
    e 1 3 20
    t # 2
    v 0 6
    v 1 11
    e 0 1 13
    t # 3
    v 0 2
    v 1 11
    v 2 19
    v 3 2
    e 0 1 15
    e 1 2 11
    e 0 3 19
    t # 4
    v 0 1
    v 1 16
    v 2 14
    e 0 1 8
    e 1 2 5
    e 0 2 19

    et je veux l'améliorer surtout en ce qui concerne le temps d’exécution, donc j'ai pensé à utiliser le multithreading mais j'ai aucune idée d'où commencer. J'ai lu quelques exemples (la plupart utilise les méthodes et les fonctions qui ne sont pas dans mon programme).

    J'attends vos propositions.

    voila le 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
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    #include <boost/graph/adjacency_list.hpp>
    #include <boost/graph/vf2_sub_graph_iso.hpp>
    #include <fstream>
    #include <iostream>
    #include <string>
    #include <vector>
    #include <ctime>
    using namespace std;
    using namespace boost;
     
    /*********************************************/
    // vertex
    struct VertexProperties {
        int id;
        int label;
        VertexProperties(unsigned i=0, unsigned l=0) : id(i), label(l) {}
    };
     
    // edge
    struct EdgeProperties {
        unsigned id;
        unsigned label;
        EdgeProperties(unsigned i=0, unsigned l=0) : id(i), label(l) {}
    };
     
    // Graph
    struct GraphProperties {
        unsigned id;
        unsigned label;
        GraphProperties(unsigned i=0, unsigned l=0) : id(i), label(l) {}
    };
     
    // adjency list
    typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS,
            VertexProperties,
            EdgeProperties,
            GraphProperties> Graph;
     
    // descriptors
     
    typedef boost::graph_traits<Graph>::vertex_descriptor vertex_t;
    typedef std::pair<boost::graph_traits<Graph>::edge_descriptor, bool> edge_t;
    // iterators
    typedef graph_traits<Graph>::vertex_iterator vertex_iter;
    typedef graph_traits<Graph>::edge_iterator edge_iter;
     
    int main()
    {
        clock_t start=std::clock();
        std::vector<Graph> dataG;
     
        std::ifstream file_reader("1000.data"); // flux d'entrée pour opérer sur les fichiers.
        //ifstream * file_reader= new ifstream("60.txt" ); //flux d'entrée pour opérer sur les fichiers.
     
        std::string line;
        while (std::getline(file_reader, line)) { // getline reads characters from an input stream and places them into a string
     
            char lineType;
     
            std::stringstream ss(line);  // use a string buffer that contains a sequence of characters.
            if (ss >> lineType) switch (lineType) {
                case 't':
                    {
                        char diez;
                        unsigned gid;
                        if (ss >> diez >> gid) {
                            dataG.emplace_back(GraphProperties (gid, gid));
                            //dataG.push_back(GraphProperties (gid, gid));
                        }
                        else throw std::runtime_error("Error parsing '" + line + "'");
                    }
                    break;
                case 'v':
                    {
                        assert(!dataG.empty());
     
                        int vId, vLabel;
                        if (ss >> vId >> vLabel) {
                            boost::add_vertex(VertexProperties(vId, vLabel), dataG.back());
                        }
                        else throw std::runtime_error("Error parsing '" + line + "'");
                    }
                    break;
                case 'e':
                    {
                        assert(!dataG.empty());
     
                        int fromId, toId, vLabel;
                        if (ss >> fromId >> toId >> vLabel) {
                            // Note that the EdgeProperty.id doesn't make sense with your input data
                            // as it only contains [vertexFrom vertexTo edgeData]
                            boost::add_edge(fromId, toId, EdgeProperties(vLabel, vLabel), dataG.back());
                        }
                        else throw std::runtime_error("Error parsing '" + line + "'");
                    }
                    break;
            } else
            {
                // ignoring empty line
            }
        }
    }

  2. #2
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    As-tu idée de ce que tu veux distribuer?
    Qu'y gagneras-tu?

    Sans réponses à ces deux questions, n'essaie même pas de multi-threader.
    En général, ajouter un thread permet de séparer par exemple l'interface graphique du traitement.

    Ajouter des threads ne peut servir que si on sait qu'on y gagnera.
    Dans le cas contraire, ca risque de ralentir l'exécution du programme, et ca va forcément beaucoup ralentir son développement et sa clarté.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  3. #3
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    338
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 338
    Points : 0
    Points
    0
    Par défaut
    Au fait, je veux utiliser les threads pour la lecture de chaque graphe pour gagner plus de temps.
    j'ai modifié le programme précédent:
    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
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    #include <boost/graph/adjacency_list.hpp>
    #include <boost/graph/vf2_sub_graph_iso.hpp>
    #include <fstream>
    #include <iostream>
    #include <string>
    #include <vector>
    #include <ctime>
    using namespace std;
    using namespace boost;
     
    /*********************************************/
    // vertex
    struct VertexProperties {
        int id;
        int label;
        VertexProperties(unsigned i=0, unsigned l=0) : id(i), label(l) {}
    };
     
    // edge
    struct EdgeProperties {
        unsigned id;
        unsigned label;
        EdgeProperties(unsigned i=0, unsigned l=0) : id(i), label(l) {}
    };
     
    // Graph
    struct GraphProperties {
        unsigned id;
        unsigned label;
        GraphProperties(unsigned i=0, unsigned l=0) : id(i), label(l) {}
    };
     
    // adjency list
    typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, 
            VertexProperties, 
            EdgeProperties,
            GraphProperties> Graph;
     
    // descriptors
     
    typedef boost::graph_traits<Graph>::vertex_descriptor vertex_t;
    typedef std::pair<boost::graph_traits<Graph>::edge_descriptor, bool> edge_t;
    // iterators
    typedef graph_traits<Graph>::vertex_iterator vertex_iter;
    typedef graph_traits<Graph>::edge_iterator edge_iter;
    //==================================================================================
    std::vector<Graph> readandcreategraphs(string fich)
    {
    	std::vector<Graph> vect;
     
        std::ifstream file_reader(fich); // flux d'entrée pour opérer sur les fichiers.
        //ifstream * file_reader= new ifstream("60.txt" ); //flux d'entrée pour opérer sur les fichiers.
     
        std::string line;
        while (std::getline(file_reader, line)) { // getline reads characters from an input stream and places them into a string
     
            char lineType;
     
            std::stringstream ss(line);  // use a string buffer that contains a sequence of characters.
            if (ss >> lineType) switch (lineType) {
                case 't':
                    {
                        char diez;
                        unsigned gid;
                        if (ss >> diez >> gid) {
                            vect.emplace_back(GraphProperties (gid, gid));//1000.data>>3,381s
                            //vect.push_back(GraphProperties (gid, gid));//1000.data>>3,7776s
                        }
                        else throw std::runtime_error("Error parsing '" + line + "'");
                    }
                    break;
                case 'v':
                    {
                        assert(!vect.empty());
     
                        int vId, vLabel;
                        if (ss >> vId >> vLabel) {
                            boost::add_vertex(VertexProperties(vId, vLabel), vect.back());
                        }
                        else throw std::runtime_error("Error parsing '" + line + "'");
                    }
                    break;
                case 'e':
                    {
                        assert(!vect.empty());
     
                        int fromId, toId, vLabel;
                        if (ss >> fromId >> toId >> vLabel) {
                            // Note that the EdgeProperty.id doesn't make sense with your input data
                            // as it only contains [vertexFrom vertexTo edgeData]
                            boost::add_edge(fromId, toId, EdgeProperties(vLabel, vLabel), vect.back());
                        }
                        else throw std::runtime_error("Error parsing '" + line + "'");
                    }
                    break;
            } else
            {
                // ignoring empty line
            }
        }
     return vect;
    }
     
    //==================================================================================
     
    int main() 
    {
    	clock_t start=std::clock();
    	std::vector<Graph> dataG= readandcreategraphs("1000.data");
    //std::cout << "Lecture et creation de:" << dataG.size() << " graphs " << std::endl;
       	Graph testg;
       	typedef std::pair<edge_iter, edge_iter> edge_pair;
     
        cout<<"TIME: "<<( std::clock() - start ) / (double) CLOCKS_PER_SEC<<"s"<<endl; // fin du programme.
     
    }

  4. #4
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Tu n'y gagneras rien, parce que le problème c'est que tes graphes sont dans un/des fichiers, et qu'il faut lire ces fichiers.
    Ce n'est pas tellement le graphe qui pose problème, mais le disque dur.

    éventuellement, recherche du coté de mmap.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  5. #5
    Membre émérite
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    852
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 852
    Points : 2 298
    Points
    2 298
    Par défaut
    Si il fait du traitement sur les fichiers, il peut threader l'appel à mmap pendant que le thread principal fait son traitement, ça sera toujours ça de gagner.

  6. #6
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Si tu débutes avec C++, tu n'en es pas à threader.
    Un thread n'est pas un baguette magique, c'est un moyen de répartir le travail.

    Encore faut-il savoir quel travail peut-être fait à coté d'un autre, et en quoi ca n'utilise pas le même ressources (ici un fichier)
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  7. #7
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    338
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 338
    Points : 0
    Points
    0
    Par défaut
    Citation Envoyé par leternel Voir le message
    Si tu débutes avec C++, tu n'en es pas à threader.
    Un thread n'est pas un baguette magique, c'est un moyen de répartir le travail.

    Encore faut-il savoir quel travail peut-être fait à coté d'un autre, et en quoi ca n'utilise pas le même ressources (ici un fichier)

    Pour gagner en temps je veux créer un thread qui génère un graphe et l'ajoute au vecteur pendant que le programme principal continue à lire le fichier. sinon existe-t-il un autre moyen pour amélioré le programme?

  8. #8
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    338
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 338
    Points : 0
    Points
    0
    Par défaut
    Citation Envoyé par leternel Voir le message
    Tu n'y gagneras rien, parce que le problème c'est que tes graphes sont dans un/des fichiers, et qu'il faut lire ces fichiers.
    Ce n'est pas tellement le graphe qui pose problème, mais le disque dur.

    éventuellement, recherche du coté de mmap.
    ça veux dire quoi le mmap ?

  9. #9
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Tu ne peux pas continuer à lire le fichier pendant que tu le lis.
    Si encore tu avais plusieurs fichiers, tu pourrais charger chacun dans un thread (en réutilisant les threads qui ont déjà fini... cf thread pool)

    Un fichier, c'est rare et cher. c'est même pour ca qu'un fstream n'est pas copiable.
    Ca n'est pas vraiment partageable entre threads.

    En regardant ton code, tout me parait légitime.
    Par contre, je pense que tu ne compiles pas avec les optimisations de performances.
    Pour gcc, c'est -O2, voire -O3, si vraiment c'est nécessaire.



    mmap est une fonction qui permet de "mapper en mémoire" un fichier, et donc de charger un fichier plus vite.
    Par contre, derrière, tu le manipules comme un énorme tableau de char.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  10. #10
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    338
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 338
    Points : 0
    Points
    0
    Par défaut
    Citation Envoyé par leternel Voir le message
    Tu ne peux pas continuer à lire le fichier pendant que tu le lis.
    Si encore tu avais plusieurs fichiers, tu pourrais charger chacun dans un thread (en réutilisant les threads qui ont déjà fini... cf thread pool)

    Un fichier, c'est rare et cher. c'est même pour ca qu'un fstream n'est pas copiable.
    Ca n'est pas vraiment partageable entre threads.

    En regardant ton code, tout me parait légitime.
    Par contre, je pense que tu ne compiles pas avec les optimisations de performances.
    Pour gcc, c'est -O2, voire -O3, si vraiment c'est nécessaire.



    mmap est une fonction qui permet de "mapper en mémoire" un fichier, et donc de charger un fichier plus vite.
    Par contre, derrière, tu le manipules comme un énorme tableau de char.
    Au fait, après la lecture d'un graphe (t #) je veux faire un thread qui s'occupe de la création du graphe , pendant que le thread fait les insertions nécessaires, la lecture du fichier des graphes continue en parallèle.

  11. #11
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Et bien, c'est assez simple:
    Tu crées une structure premisse (un vector<std::string>?) contenant les lignes lues.
    Ta boucle de lecture consiste à "lire une premisse puis l'injecter dans une file, tant qu'il y a quelque chose à lire, puis clore la file."
    Ta boucle de création ressemble à "tant que la file n'est pas close, prendre une prémisse et faire un graphe."

    Un thread, et puis c'est tout.
    Regarde du coté de std::thread
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  12. #12
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Citation Envoyé par leternel Voir le message
    Ta boucle de lecture consiste à "lire une premisse puis l'injecter dans une file, tant qu'il y a quelque chose à lire, puis clore la file."
    Ta boucle de création ressemble à "tant que la file n'est pas close, prendre une prémisse et faire un graphe."
    Attention à la concurrence, la file doit être thread_safe. Il faudrait probablement utiliser des locks.

    Avant de vouloir multi-threader, il faut t'assurer que c'est vraiment cela qui pose problème. Et pour le faire, il faut profiler l'exécution de ton programme. Si après profiling, IO disque utilise 90 % du temps d'exécution, ça sert à rien de t'ermmerder à multi-threader car tu n'as grand chose à gagner, tu pourrais même empirer la situation vu que tu es débutant. Profling d'abord, optimisation après.
    Find me on github

  13. #13
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    338
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 338
    Points : 0
    Points
    0
    Par défaut
    Citation Envoyé par jblecanard Voir le message
    Attention à la concurrence, la file doit être thread_safe. Il faudrait probablement utiliser des locks.

    Avant de vouloir multi-threader, il faut t'assurer que c'est vraiment cela qui pose problème. Et pour le faire, il faut profiler l'exécution de ton programme. Si après profiling, IO disque utilise 90 % du temps d'exécution, ça sert à rien de t'ermmerder à multi-threader car tu n'as grand chose à gagner, tu pourrais même empirer la situation vu que tu es débutant. Profling d'abord, optimisation après.
    Comment faire le Profling svp !

  14. #14
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Avec un profiler, tel que gprofile ou valgrind (si je ne me trompe pas).

    Cherche "<ton os> profiler c++".
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  15. #15
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Les Google Perf Tools sont bien pour ça car pas trop coûteux à l'exécution, ce qui permet de mieux représenter le coût de l'IO en elle-même.
    Find me on github

  16. #16
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    338
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 338
    Points : 0
    Points
    0
    Par défaut
    J'ai utilisé gprof sur 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
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
     
    #include <boost/graph/adjacency_list.hpp>
    #include <boost/graph/vf2_sub_graph_iso.hpp>
    #include <fstream>
    #include <iostream>
    #include <string>
    #include <vector>
    #include <ctime>
    using namespace std;
    using namespace boost;
     
    /*********************************************/
    // vertex
    struct VertexProperties {
        int id;
        int label;
        VertexProperties(unsigned i=0, unsigned l=0) : id(i), label(l) {}
    };
     
    // edge
    struct EdgeProperties {
        unsigned id;
        unsigned label;
        EdgeProperties(unsigned i=0, unsigned l=0) : id(i), label(l) {}
    };
     
    // Graph
    struct GraphProperties {
        unsigned id;
        unsigned label;
        GraphProperties(unsigned i=0, unsigned l=0) : id(i), label(l) {}
    };
     
    // adjency list
    typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, 
            VertexProperties, 
            EdgeProperties,
            GraphProperties> Graph;
     
    // descriptors
     
    typedef boost::graph_traits<Graph>::vertex_descriptor vertex_t;
    typedef std::pair<boost::graph_traits<Graph>::edge_descriptor, bool> edge_t;
    // iterators
    typedef graph_traits<Graph>::vertex_iterator vertex_iter;
    typedef graph_traits<Graph>::edge_iterator edge_iter;
    //==================================================================================
    std::vector<Graph> readandcreategraphs(string fich)
    {
    	std::vector<Graph> vect;
     
        std::ifstream file_reader(fich); // flux d'entrée pour opérer sur les fichiers.
        //ifstream * file_reader= new ifstream("60.txt" ); //flux d'entrée pour opérer sur les fichiers.
     
        std::string line;
        while (std::getline(file_reader, line)) { // getline reads characters from an input stream and places them into a string
     
            char lineType;
     
            std::stringstream ss(line);  // use a string buffer that contains a sequence of characters.
            if (ss >> lineType) switch (lineType) {
                case 't':
                    {
                        char diez;
                        unsigned gid;
                        if (ss >> diez >> gid) {
                            vect.emplace_back(GraphProperties (gid, gid));//1000.data>>3,381s
                            //vect.push_back(GraphProperties (gid, gid));//1000.data>>3,7776s
                        }
                        else throw std::runtime_error("Error parsing '" + line + "'");
                    }
                    break;
                case 'v':
                    {
                        assert(!vect.empty());
     
                        int vId, vLabel;
                        if (ss >> vId >> vLabel) {
                            boost::add_vertex(VertexProperties(vId, vLabel), vect.back());
                        }
                        else throw std::runtime_error("Error parsing '" + line + "'");
                    }
                    break;
                case 'e':
                    {
                        assert(!vect.empty());
     
                        int fromId, toId, vLabel;
                        if (ss >> fromId >> toId >> vLabel) {
                            // Note that the EdgeProperty.id doesn't make sense with your input data
                            // as it only contains [vertexFrom vertexTo edgeData]
                            boost::add_edge(fromId, toId, EdgeProperties(vLabel, vLabel), vect.back());
                        }
                        else throw std::runtime_error("Error parsing '" + line + "'");
                    }
                    break;
            } else
            {
                // ignoring empty line
            }
        }
     return vect;
    }
     
    //==================================================================================
     
    int main() 
    {
    	clock_t start=std::clock();
    	std::vector<Graph> dataG= readandcreategraphs("5.txt");
    //std::cout << "Lecture et creation de:" << dataG.size() << " graphs " << std::endl;
       	Graph testg;
       	typedef std::pair<edge_iter, edge_iter> edge_pair;
     
        cout<<"TIME: "<<( std::clock() - start ) / (double) CLOCKS_PER_SEC<<"s"<<endl; // fin du programme.
     
          typedef std::pair<edge_iter, edge_iter> edge_pair;
     
          int c = 0; //compteur de dataG
          for (auto gr : dataG)
          {
     
            std::cout << "* * * Graph " << c << " * * * contains " << num_vertices(gr) << " vertices, and " << num_edges(gr) << " edges " << std::endl;        
            //Vertex list
            std::cout << "  Vertex list: " << std::endl;
            for (size_t i = 0 ; i < num_vertices(gr) ; ++i) //size_t vertice number in the graph
            {
              std::cout << "   v[" << i << "]   ID: " << gr[i].id << ", Label: " << gr[i].label << std::endl;
            }
            //Edge list
            std::cout << "  Edge list: " << std::endl;
            edge_pair ep;
            for (ep = edges(gr); ep.first != ep.second; ++ep.first) //ep edge number 
            {
              vertex_t from = source(*ep.first, gr);
              vertex_t to = target(*ep.first, gr);
              edge_t edg = edge(from, to, gr);
              std::cout << "   e(" << gr[from].label << "," << gr[to].label << ")   ID: " << gr[edg.first].id << " ,  Label: " <<  gr[edg.first].label << std::endl;
            }
            std::cout << std::endl;
            c++;
          }
     
    }
    Voila ce que j'obtiens (aidez-moi à le comprendre svp)
    Fichiers attachés Fichiers attachés

  17. #17
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Et qu'en déduis-tu?
    Perso, je ne vois que des 0, donc la partie profilée (les fonctions non système) sont déjà sans impact sur les performances.

    C'est ton fichier qui ralenti tout.
    Où est-il? (disque dur local ou externe, lecteur réseau)
    Quelle taille fait-il?

    Combien de temps prends ton programme sur ce fichier?
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  18. #18
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    338
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 338
    Points : 0
    Points
    0
    Par défaut
    Le fichier se trouve dans le même emplacement du programme.

  19. #19
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Ca ne dit pas s'il est sur le réseau ou non.
    Ton programme est peut-être lent à charger en mémoire, lui aussi.

    En gros, les performances sont limitées par le plus lent sous-système utilisé.
    Ici, il y en a que trois:
    l'accès au fichier
    le swap sur disque si les données sont plus grandes que la ram réellement disponible.
    le processeur.

    Comme tu ne calcules pratiquement rien, le proc est hors de cause, reste l'accès au donnée.
    D'ou ma question sur l'emplacement physique du fichier.

    En effet, la bande passante d'un disque dur, c'est de l'ordre du Go/s, la ram est au moins dix fois plus rapide, tandis que les réseaux les plus performants atteigne le Gbits/s, soit 8 fois moins qu'un disque.
    et l'usb est plus lent qu'un disque, mais moins que le réseau (je n'ai plus les chiffres).
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  20. #20
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    338
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 338
    Points : 0
    Points
    0
    Par défaut
    J'ai modifié le programme, maintenant il lit tout le fichier pour le mettre dans une variable de type string, puis il va faire le traitement nécessaire et la création des graphes.Comment utiliser les threads maintenant !
    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
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    #include <boost/graph/adjacency_list.hpp>
    #include <boost/graph/vf2_sub_graph_iso.hpp>
    #include <boost/algorithm/string/split.hpp>
    #include <boost/algorithm/string/classification.hpp>
    #include <fstream>
    #include <iostream>
    #include <string>
    #include <vector>
    #include <algorithm>
    #include <ctime>
    using namespace std;
    using namespace boost;
     
    /*********************************************/
    // vertex
    struct VertexProperties {
        int id;
        int label;
        VertexProperties(unsigned i=0, unsigned l=0) : id(i), label(l) {}
    };
     
    // edge
    struct EdgeProperties {
        unsigned id;
        unsigned label;
        EdgeProperties(unsigned i=0, unsigned l=0) : id(i), label(l) {}
    };
     
    // Graph
    struct GraphProperties {
        unsigned id;
        unsigned label;
        GraphProperties(unsigned i=0, unsigned l=0) : id(i), label(l) {}
    };
     
    // adjency list
    typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS,
            VertexProperties,
            EdgeProperties,
            GraphProperties> Graph;
     
    // descriptors
     
    typedef boost::graph_traits<Graph>::vertex_descriptor vertex_t;
    typedef std::pair<boost::graph_traits<Graph>::edge_descriptor, bool> edge_t;
    // iterators
    typedef graph_traits<Graph>::vertex_iterator vertex_iter;
    typedef graph_traits<Graph>::edge_iterator edge_iter;
    //==================================================================================
    std::string readfromfile(string fich)
    {
        ifstream inFile;
        inFile.open(fich);//open the input file
     
        stringstream strStream;
        strStream << inFile.rdbuf();//read the file
        return strStream.str();//str holds the content of the file
     
    }
    //===========================================================
    vector<string>  splitstringtolines(string str)
    {
        vector<string> split_vector;
        split(split_vector, str, is_any_of("\n"));
     
        return split_vector;
    }
    //============================================================
    std::vector<string> readgraphs(string fich)
    {
     
     
        std::ifstream file_reader(fich); // flux d'entrée pour opérer sur les fichiers.
        //ifstream * file_reader= new ifstream("60.txt" ); //flux d'entrée pour opérer sur les fichiers.
     
        std::string l;
        std::vector<string> fichlines;
        while (std::getline(file_reader, l))
        { // getline reads characters from an input stream and places them into a string
            fichlines.emplace_back(l);       
        }
     
     
     return fichlines;
    }
     
    //==============================================================
    std::vector<Graph> creategraphs(std::vector<string> fichlines)
    {
        std::vector<Graph> vect;
        for (string line:fichlines)
        {
            char lineType;
     
            std::stringstream ss(line);  // use a string buffer that contains a sequence of characters.
            if (ss >> lineType) switch (lineType) {
                case 't':
                    {
                        char diez;
                        unsigned gid;
                        if (ss >> diez >> gid) {
                            vect.emplace_back(GraphProperties (gid, gid));//1000.data>>3,381s
                            //vect.push_back(GraphProperties (gid, gid));//1000.data>>3,7776s
                        }
                        else throw std::runtime_error("Error parsing '" + line + "'");
                    }
                    break;
                case 'v':
                    {
                        assert(!vect.empty());
     
                        int vId, vLabel;
                        if (ss >> vId >> vLabel) {
                            boost::add_vertex(VertexProperties(vId, vLabel), vect.back());
                        }
                        else throw std::runtime_error("Error parsing '" + line + "'");
                    }
                    break;
                case 'e':
                    {
                        assert(!vect.empty());
     
                        int fromId, toId, vLabel;
                        if (ss >> fromId >> toId >> vLabel) {
                            // Note that the EdgeProperty.id doesn't make sense with your input data
                            // as it only contains [vertexFrom vertexTo edgeData]
                            boost::add_edge(fromId, toId, EdgeProperties(vLabel, vLabel), vect.back());
                        }
                        else throw std::runtime_error("Error parsing '" + line + "'");
                    }
                    break;
            } else
            {
                // ignoring empty line
            }
     
        }
        /*
         
        */
     
        return vect;
    }
     
     
    int main()
    {
        clock_t start=std::clock();
        std::vector<Graph> data =creategraphs(splitstringtolines(readfromfile("60.txt")));
        cout<<">>>>>>>> TIME: "<<( std::clock() - start ) / (double) CLOCKS_PER_SEC<<"s"<<endl;
    }

    et comment accéder au information du graphe?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::cout << "* * * Graph " << gr.label << std::endl;
    ne fonctionne pas

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