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 :

Probl�me avec une HashMap (STL/SGI)


Sujet :

C++

  1. #1
    Membre r�gulier
    Profil pro
    Inscrit en
    F�vrier 2011
    Messages
    11
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2011
    Messages : 11
    Par d�faut Probl�me avec une HashMap (STL/SGI)
    Bonjour,

    Alors j'aimerais indexer dans une hashMap tout plein de k-mer de plusieurs millions de mots diff�rents.
    J'utilise l'extension de la hashMap d�velopp�e par SGI pour r�pondre � ce probl�me.
    Voici mon 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
     
    ----> inclusion de l'extension SGI
     
    #include <ext/hash_map>
     
    using namespace std;
    namespace std { using namespace __gnu_cxx; }
     
    ----> utilisation du hasher proposé par SGI
    struct eqstr{
      bool operator()(const char* s1, const char* s2) const {
        return strcmp(s1,s2)==0;
      }
    };
     
    -----> le block associé à la hash
     
    int main(int argc, char **argv)
    {
    // initialisation
     hash_map<const char*, int, hash<const char*>, eqstr> hash_kmer;
     ...
     ... 
     ullong cpt = 0;
     uint lg_kmer = k; // k une longueur fixe, plus petite que la taille du plus petit mot... 
     while (cpt < nb_mots) {
        tousLesMots.getline(mot_actuel, lg_mot+1);
        for (ullong i = 0 ; i < (lg_mot-lg_kmer) ; i++){
          facteur = (mot_actuel.substr(i,lg_kmer)).c_str();
          hash_kmer[facteur] ++ ;
        }
        cpt++;
      }
      ...
      ...
      return 0;
    }
    Le probl�me est que c'est tr�s tr�s lent !
    Par exemple, en prenant des mots de longueurs 75 et un k-mer de longueur 22, pour un nombre de mots de 45 millions, il faut 8 heures pour faire tourner le programme (sur une machine puissante).

    Au d�but, je pensais que c'�tait la gestion des collisions qui prenait beaucoup de temps. De ce fait, j'ai diminu� la longueur de k pour avoir moins de collisions. Sauf que, pour le m�me exemple, mais avec un k de longueur 10 �a met 15 heures, donc deux fois plus de temps.

    Je pense que c'est mon implantation qui n'est pas bonne (ou peut-�tre le hasher que j'utilise). C'est pour cela que je me retourne vers vous car je ne suis pas plus comp�tant que �a dans les hashMap.
    PS : j'ai test� d'autres implantation de hash telles que google-sparse ou google-dense mais �a ne change rien.
    De plus dans ce comparatif, SGI n'est pas trop mal situ�e :
    http://attractivechaos.awardspace.com/udb.html

    Qui aurait une id�e de ce probl�me de lenteur ????

    Merci d'avance,

    Nicolas P

  2. #2
    Membre Expert

    Inscrit en
    Mai 2008
    Messages
    1 014
    D�tails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Par d�faut
    Bonsoir,

    Peut-�tre pourrais tu nous mettre le code complet vu qu'il n'a pas l'air tr�s long ? (avec la balise code). Et nous mettre un lien vers un exemple de base de mots pour qu'on puisse essayer nous-m�me et voir la cause de la lenteur.

    En attendant :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    // ----> utilisation du hasher proposé par SGI
    struct eqstr{
    bool operator()(const char* s1, const char* s2) const {
    return strcmp(s1,s2)==0;
    }
    };
    Pourquoi le commentaire parle de "l'utilisation du hasher", alors que la structure eqstr ne d�finit pas de fonction de hash, juste une fonction de comparaison !?

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    while (cpt < nb_mots) {
    tousLesMots.getline(mot_actuel, lg_mot+1);
    for (ullong i = 0 ; i < (lg_mot-lg_kmer) ; i++){
    facteur = (mot_actuel.substr(i,lg_kmer)).c_str();
    hash_kmer[facteur] ++ ;
    }
    humhum. Difficile de juger du code sans conna�tre la d�finition de tousLesMots, mot_actuel etc. mais ce bout de code a l�air tr�s suspect quand m�me. On a l'impression que tu mets dans ta table de hash un pointeur vers un objet temporaire (mot_actuel.substr())

  3. #3
    Membre r�gulier
    Profil pro
    Inscrit en
    F�vrier 2011
    Messages
    11
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2011
    Messages : 11
    Par d�faut
    Oui en effet, je me suis tromp� dans mon commentaire, �a c'est suelement l'equalKey que j'utilise. Je voulais juste dire que j'utilisais la fonction de hashage par d�faut...

    Pour mon code, je vous l'envoie tel qu'il est. J'ai voulu couper pour simplifier un peu mais c'�tait pas une bonne id�e finalement

    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
     
     
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <sys/time.h>
    #include <ext/hash_map>
    extern "C" {
    #include <time.h>
    }
     
    using namespace std;
    namespace std { using namespace __gnu_cxx; }
     
    #ifndef ullong
    #define ullong unsigned long long
    #endif
     
    ullong getChrono() {
      struct timeval time;
      time_t sec;
      suseconds_t usec;
     
      if (gettimeofday(&time,NULL) != -1) {
        sec = time.tv_sec;
        usec = time.tv_usec;
        return (ullong)sec*1000000+usec;
      }
      return 0;
    }
     
    struct eqstr{
      bool operator()(const char* s1, const char* s2) const {
        return strcmp(s1,s2)==0;
      }
    };
     
    int main(int argc, char **argv)
    {
      if (argc < 4){
        cerr << "Usage: " << argv[0] <<" read_file read_length threshold" << endl; 
        exit(1);
      }
      ullong start = getChrono();
     
      ifstream reads;
      reads.open(argv[1], ios::in);
      if (! reads.is_open()) {
        cerr << "Cannot open reads file: " << argv[1] << endl;
        exit(2);
      }
      reads.seekg (0, ios::end);
      ullong length = reads.tellg();
      int read_length = atoi(argv[2]);
      char *line = new char[read_length+1];
      reads.seekg (0, ios::beg);
      ullong nb_reads = length/(read_length+1);
      int threshold= atoi(argv[3]);
     
      hash_map<const char*, int, hash<const char*>, eqstr> hash_kmer;
     
      string read_string;
      const char *factor = new char[threshold+1];
      ullong current = 0;
     
      while (current < nb_reads) {
        reads.getline(line, read_length+1);
        read_string = line;
        for (ullong i = 0 ; i < (read_length-threshold) ; i++){
          factor = (read_string.substr(i,threshold)).c_str();
          hash_kmer[factor] ++ ;
        }
        current++;
      }  
      cout << "nb_factors indexed in hash_kmer: " << hash_kmer.size() << endl;
      cerr << "Creation of stl_hash_map: " << (getChrono()-start)/1000000. << " s" << endl;
      return 0;
    }

    Pour le lien avec un fichier de donn�e :
    http://www.lirmm.fr/~nphilippe/test

    Merci encore

    Nicolas P

  4. #4
    r0d
    r0d est d�connect�
    Membre exp�riment�

    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Ao�t 2004
    Messages
    4 299
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rh�ne Alpes)

    Informations professionnelles :
    Activit� : D�veloppeur informatique

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 4 299
    Billets dans le blog
    2
    Par d�faut
    Bonjour,

    au cas o�, ne sait-on jamais: �tes-vous bien certain de compiler avec les optimisations de compilation ad�quates?

  5. #5
    screetch
    Invit�(e)
    Par d�faut
    c'est deja un miracle que ca marche.
    Comme dit plus haut:

    humhum. Difficile de juger du code sans conna�tre la d�finition de tousLesMots, mot_actuel etc. mais ce bout de code a l�air tr�s suspect quand m�me. On a l'impression que tu mets dans ta table de hash un pointeur vers un objet temporaire (mot_actuel.substr())
    le gros avantage c'est que tu n'alloues presque pas de m�moire (en tous cas pas pour les chaines).
    Le gros inconvenient c'est que tu stockes probablement toute les chaines dans le meme bloc memoire (elles s'ecrasent les unes les autres). Toute les comparaisons de chaines etc etc sont probablement fauss�es.

    Sinon, tu pourrais afficher une sorte de barre de progres ou de ETA; ca pourrait aider a voir si il y a un probleme de complexit�, ou bien si le programme s'arrete periodiquement...

  6. #6
    Membre r�gulier
    Profil pro
    Inscrit en
    F�vrier 2011
    Messages
    11
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2011
    Messages : 11
    Par d�faut
    C'est possible que ce soit � cause de �a, mais j'suis septique.
    Au cas o�, voila ma ligne de compilation :
    g++ -Wall -Wextra -ansi -g -O2 -funroll-loops buildSTLHash.cpp -o buildSTLHash

    En fait c'est vraiment tr�s visuel ! �a commence � patiner dans la semoule � partir d'un certain moment.
    Sur l'exemple que j'ai donn� en lien, voici la trace de mon programme pour un k-mer de lg 22.

    Au d�but de l' ex�cution du programme, �a se comporte tr�s normalement :

    10000 reads is included in stl_hash in 0.110646 s
    20000 reads is included in stl_hash in 0.214687 s
    30000 reads is included in stl_hash in 0.297762 s
    40000 reads is included in stl_hash in 0.423303 s
    50000 reads is included in stl_hash in 0.609714 s
    60000 reads is included in stl_hash in 0.771651 s
    70000 reads is included in stl_hash in 0.859677 s
    80000 reads is included in stl_hash in 0.976118 s
    90000 reads is included in stl_hash in 1.28819 s
    100000 reads is included in stl_hash in 1.40297 s
    110000 reads is included in stl_hash in 1.49794 s
    120000 reads is included in stl_hash in 1.59264 s
    130000 reads is included in stl_hash in 1.73249 s
    140000 reads is included in stl_hash in 1.85493 s
    150000 reads is included in stl_hash in 1.9604 s
    160000 reads is included in stl_hash in 2.07579 s
    170000 reads is included in stl_hash in 2.61795 s
    180000 reads is included in stl_hash in 2.74023 s
    190000 reads is included in stl_hash in 2.84681 s
    200000 reads is included in stl_hash in 3.01806 s
    210000 reads is included in stl_hash in 3.11888 s
    220000 reads is included in stl_hash in 3.21828 s
    230000 reads is included in stl_hash in 3.31929 s
    240000 reads is included in stl_hash in 3.42316 s
    250000 reads is included in stl_hash in 3.53848 s
    260000 reads is included in stl_hash in 3.65708 s
    270000 reads is included in stl_hash in 3.93243 s
    280000 reads is included in stl_hash in 4.05486 s
    290000 reads is included in stl_hash in 4.18682 s
    300000 reads is included in stl_hash in 4.29214 s
    310000 reads is included in stl_hash in 4.42333 s

    Soit 310 000 reads pour 4 secondes

    Et � partir d'un moment :

    17960000 reads is included in stl_hash in 1902.34 s
    17970000 reads is included in stl_hash in 1907.72 s
    17980000 reads is included in stl_hash in 1913.17 s
    17990000 reads is included in stl_hash in 1918.09 s
    18000000 reads is included in stl_hash in 1924.37 s
    18010000 reads is included in stl_hash in 1931.79 s
    18020000 reads is included in stl_hash in 1935.82 s
    18030000 reads is included in stl_hash in 1940.33 s
    18040000 reads is included in stl_hash in 1942.89 s
    18050000 reads is included in stl_hash in 1949.09 s
    18060000 reads is included in stl_hash in 1954.16 s

    Soit 100 000 reads pour 52 secondes. Et c'est de pire en pire...

    Peut-�tre qu'il y a de plus en plus de conflits � g�rer ? Mais dans ce cas l�, en r�duisant la longueur du k-mer je devrais gagner de la vitesse, puisque j'ai moins de cl�s distinctes, non ?

    Je ne suis vraiment pas un sp�cialiste des hashMap, donc n'h�sitez-pas � me donner toutes sortes de suggestions ou d'informations, �a ne me sera que b�n�fique.

    Merci,

    Nicolas P

  7. #7
    screetch
    Invit�(e)
    Par d�faut
    il faut vraiment corriger ton probl�me de chaines temporaires qui sont ecras�es; imagines que maintenant toute tes comparaisons sont fauss�es, on est pas du tout dans le cas optimal pour un hash_map.

    Pour t'expliquer ce qui se passe, les cl�s sont effac�es au fur et a mesure et probablement ecras�es par de nouvelles cl�s. Tu as un hash_map ou les cl�s sont donc presque surement chang�es apr�s insertion, voire pire.

  8. #8
    Membre r�gulier
    Profil pro
    Inscrit en
    F�vrier 2011
    Messages
    11
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2011
    Messages : 11
    Par d�faut
    Il me semble que j'avais fait un cout des cl�s et des valeurs sur un petit exemple. �a correspondait aux bons r�sultats. Je me suis dis que c'�tait la valeur point�e qui �tait recopi�e dans la hash mais je comprends bien le probl�me dans le cas o� c'est directement l'adresse qui est stock�e. Je vais cr�er un new char[threshold+1] � chaque fois, on va voir si vous avez eu le nez creux

  9. #9
    Membre averti

    Profil pro
    Inscrit en
    D�cembre 2002
    Messages
    43
    D�tails du profil
    Informations personnelles :
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations forums :
    Inscription : D�cembre 2002
    Messages : 43
    Par d�faut
    Citation Envoy� par screetch Voir le message
    le gros avantage c'est que tu n'alloues presque pas de m�moire (en tous cas pas pour les chaines).
    Le gros inconvenient c'est que tu stockes probablement toute les chaines dans le meme bloc memoire (elles s'ecrasent les unes les autres). Toute les comparaisons de chaines etc etc sont probablement fauss�es.
    Euh... sauf erreur de ma part, ce n'est pas ce qui se passe.
    Dans son code il y a :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
          factor = (read_string.substr(i,threshold)).c_str();
          hash_kmer[factor] ++ ;
    La fonction c_str() renvoit une nouvelle cha�ne � chaque fois (allou�e par les propres soins de la fonction). L'espace m�moire allou� pour cette cha�ne n'est pas lib�r�. L'adresse � laquelle est stock�e la cha�ne n'est donc jamais la m�me et les cl�s ne peuvent pas �tre �cras�es.

    En revanche, je n'ai aucune id�e pour le probl�me de lenteur. Si vraiment elles ne font pas l'affaire, il faudrait peut-�tre utiliser une autre structure que les tables de hash, qui ne seraient peut-�tre pas adapt�es � ce probl�me.

  10. #10
    Membre r�gulier
    Profil pro
    Inscrit en
    F�vrier 2011
    Messages
    11
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2011
    Messages : 11
    Par d�faut
    Citation Envoy� par screetch Voir le message
    il faut vraiment corriger ton probl�me de chaines temporaires qui sont ecras�es; imagines que maintenant toute tes comparaisons sont fauss�es, on est pas du tout dans le cas optimal pour un hash_map.

    Pour t'expliquer ce qui se passe, les cl�s sont effac�es au fur et a mesure et probablement ecras�es par de nouvelles cl�s. Tu as un hash_map ou les cl�s sont donc presque surement chang�es apr�s insertion, voire pire.
    Alors si j'ai allou� un nouveau factor � chaque fois (si j'ai bien compris ce que tu m'as dis), ce qui donne :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
     
     char *factor = new char[threshold+1];
     strcopy(factor, (read_string.substr(i,threshold)).c_str());
     hash_kmer[factor] ++ ;
    Mais �a n'a pas l'air de changer grand chose, ce qui laisse (peut-�tre) � penser que la fonction c_str() fait d�j� le boulot de l'allocation (ce qui disait KaelKael).

    Par ailleurs, �a explique aussi pourquoi je retrouvais bien mes cl�s et mes valeurs. En effet, dans le cas o� les cl�s s'effaceraient au fur et � mesure, je ne vois pas comment je pourrais les retrouver � la fin :/

  11. #11
    screetch
    Invit�(e)
    Par d�faut
    c_str() ne renvoie pas une nouvelle cha�ne, il renvoie en g�n�ral le pointeur interne.
    http://www.cplusplus.com/reference/string/string/c_str/

  12. #12
    screetch
    Invit�(e)
    Par d�faut
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
     const char *factor = new char[threshold+1];
     factor = (read_string.substr(i,threshold)).c_str();
     hash_kmer[factor] ++ ;
    ce code est toujours faux; tu alloues d'abord factor, puis tu remplaces le pointeur par un autre pointeur, tu ne fais pas vraiment une copie. En gros tu as juste allou� de la memoire, qui est perdue imm�diatement. Forc�ment ca va �tre plus lent

    ca va etre chaud de le faire marcher correctement, a cause des doublons, avec des (cons de) char*.
    Au ieu de ca j'avoue que des std::string t'eviteront sans doute des maux de tete.

  13. #13
    Membre r�gulier
    Profil pro
    Inscrit en
    F�vrier 2011
    Messages
    11
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2011
    Messages : 11
    Par d�faut
    Oui je me suis rendu compte de ma connerie, c'est pour �a que j'ai �dit� mon message, mais tu as r�pondu trop vite :/

  14. #14
    Membre r�gulier
    Profil pro
    Inscrit en
    F�vrier 2011
    Messages
    11
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2011
    Messages : 11
    Par d�faut
    Citation Envoy� par screetch Voir le message
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
     const char *factor = new char[threshold+1];
     factor = (read_string.substr(i,threshold)).c_str();
     hash_kmer[factor] ++ ;
    ce code est toujours faux; tu alloues d'abord factor, puis tu remplaces le pointeur par un autre pointeur, tu ne fais pas vraiment une copie. En gros tu as juste allou� de la memoire, qui est perdue imm�diatement. Forc�ment ca va �tre plus lent

    ca va etre chaud de le faire marcher correctement, a cause des doublons, avec des (cons de) char*.
    Au ieu de ca j'avoue que des std::string t'eviteront sans doute des maux de tete.
    Oui ou simplement des char *

  15. #15
    Membre r�gulier
    Profil pro
    Inscrit en
    F�vrier 2011
    Messages
    11
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2011
    Messages : 11
    Par d�faut
    Si en fait, �a fonctionne beaucoup mieux . �a ne changeait pas grand chose car vu que �a n'�crase pas les anciennes valeurs, bah �a prend plus d'espace et du coup maintenant �a swap. Mais sur un exemple qui ne swap pas, j'ai des temps de construction logique.

    Finalement, j'ai les r�sultats attendus (plus logiques), c'est � dire quelque chose qui se construit vite mais qui est tr�s gourmand en m�moire
    La prochaine fois, je ferais un peu plus gaffe au retour des fonctions std::String . Cependant, je ne comprends toujours pas comment je pouvais avoir des r�sultats corrects ?
    Et puis, c'�tait quand m�me un miracle que �a passait. En effet, si je ne me trompe pas, au final j'�crasais des pointeurs de type const char * � chaque tour de boucle ? :/

  16. #16
    r0d
    r0d est d�connect�
    Membre exp�riment�

    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Ao�t 2004
    Messages
    4 299
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rh�ne Alpes)

    Informations professionnelles :
    Activit� : D�veloppeur informatique

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 4 299
    Billets dans le blog
    2
    Par d�faut
    Citation Envoy� par nphilippe1684 Voir le message
    Au cas o�, voila ma ligne de compilation :
    g++ -Wall -Wextra -ansi -g -O2 -funroll-loops buildSTLHash.cpp -o buildSTLHash
    Je connais assez mal gcc, mais je pense qu'il est possible d'am�liorer cela:
    -g c'est pour avoir les informations de debug. Pour optimiser, il faut donc l'enlever.
    sans doute qu'utiliser -O3 au lieu de -O2 sera �galement plus efficace

    Il faudrait �galement v�rifier que vous utilisez une version r�cente de gcc (en effet, le -funroll-loops qui n'est pas document� dans les derni�res versions me porte � croire que vous en utilisez une ancienne).

  17. #17
    screetch
    Invit�(e)
    Par d�faut
    a noter que les infos de debug ne veulent pas dire un code plus lent. Ca veut juste dire qu'on ajoute de quoi retrouver l'emplacement dans le code source a partir du code binaire

  18. #18
    screetch
    Invit�(e)
    Par d�faut
    @philippe: une grosse optimisation consiste a appeler un allocateur de m�moire le moins souvent possible.

    Ici il y a beaucoup d'allocations inutiles et beaucoup de "leaks" m�moire
    Pour contrer cela, au lieu d'utiliser std::string ou encore pire, un pointeur char, tu peux cr�er ta propre classe comme suit:

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class StringPrefix
    {
      char m_prefix[kmer+1]; // +1 pour le 0 terminal
    public:
      StringPrefix(const char *string)
      {
        strncpy(m_prefix, string, kmer);
      }
     
      const char *c_str() const
      {
        return m_prefix;
      }
    };
    et utiliser ca comme cl� :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    hash_map<StringPrefix, int, HashStringPrefix, EqStringPrefix > hash_kmer;
    Ca veut dire que au lieu d'allouer les cha�nes sur le tas, tu vas les copier partout ou tu en as besoin et elles seront automatiquement d�sallou�es.

    Il faudra red�finir un hash cependant, voila comment:

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    struct HashStringPrefix : public hash<const char *>
    {
    public:
      size_t operator()(const HashStringPrefix& s1, const HashStringPrefix& s2)
      {
        return operator()(s1.c_str(), s2.c_str());
      }
    };
    je suis curieux de voir les nouvelles perfs

  19. #19
    Membre r�gulier
    Profil pro
    Inscrit en
    F�vrier 2011
    Messages
    11
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2011
    Messages : 11
    Par d�faut
    Citation Envoy� par screetch Voir le message
    @philippe: une grosse optimisation consiste a appeler un allocateur de m�moire le moins souvent possible.

    Ici il y a beaucoup d'allocations inutiles et beaucoup de "leaks" m�moire
    Pour contrer cela, au lieu d'utiliser std::string ou encore pire, un pointeur char, tu peux cr�er ta propre classe comme suit:

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class StringPrefix
    {
      char m_prefix[kmer+1]; // +1 pour le 0 terminal
    public:
      StringPrefix(const char *string)
      {
        strncpy(m_prefix, string, kmer);
      }
     
      const char *c_str() const
      {
        return m_prefix;
      }
    };
    � la base, je voulais faire un test rapide, mais finalement je l'ai cod� proprement (j'esp�re). N�anmoins, ce que je veux c pas des pr�fixes mais des facteurs donc j'ai fait une classe StringFactor :
    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
     
    #include "StringFactor.h"
     
    StringFactor::StringFactor(const char *string, uint pos, uint kmer_length) {
      m_factor = new char[kmer_length+1]; // +1 pour le 0 terminal
      strncpy(m_factor, string.substr(pos,kmer_length),kmer_length);
    }
     
    ~StringFactor()::StringFactor(){
      delete [] m_factor;
    }
     
    char *c_str() const {
      return m_factor;
    }
    et utiliser ca comme cl� :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    hash_map<StringPrefix, int, HashStringPrefix, EqStringPrefix > hash_kmer;
    Ca veut dire que au lieu d'allouer les cha�nes sur le tas, tu vas les copier partout ou tu en as besoin et elles seront automatiquement d�sallou�es.
    ok On est d'accord l� dessus

    Il faudra red�finir un hash cependant, voila comment:

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    struct HashStringPrefix : public hash<const char *>
    {
    public:
      size_t operator()(const HashStringPrefix& s1, const HashStringPrefix& s2)
      {
        return operator()(s1.c_str(), s2.c_str());
      }
    };
    Bon par contre l� j'ai pas tout compris, donc j'ai essay� de faire � ma sauce :

    Pour l'h�ritage, apr�s j'ai pas surcharg� � ta fa�on "operator()" mais j'ai red�fini � cot� le EqStringFactor (c'est peut-�tre pour �a que �a compile pas) :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
     
    struct HashStringFactor : public hash<const char *>{};
     
    struct EqStringFactor{
      bool operator()(const StringFactor &s1, const StringFactor &s2) const {
        return strcmp(s1.c_str(),s2.c_str())==0;
      }
    };
    Pour l'initialisation :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
     
    hash_map<StringFactor, int, HashStringFactor, EqStringFactor > hash_kmer;

    Et enfin, pour le corps du programe :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
     
    reads.getline(line, read_length+1);
    for (ullong i = 0 ; i < (read_length-threshold) ; i++){
       StringFactor factor = StringFactor(line,i,threshold);
       hash_kmer[factor] ++ ;
    }
    Apr�s je ne suis pas �tonn� que �a me renvoie cette erreur � la compilation :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
     
    buildSGIHash.cpp:83: erreur: no match foroperator[]’ in ‘hash_kmer[factor]’
    /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/ext/hash_map:232: note: candidats sont: _Tp& __gnu_cxx::hash_map<_Key, _Tp, _HashFcn, _EqualKey, _Alloc>::operator[](const typename __gnu_cxx::hashtable<std::pair<const _Key, _Tp>, _Key, _HashFcn, std::_Select1st<std::pair<const _Key, _Tp> >, _EqualKey, _Alloc>::key_type&) [with _Key = StringFactor, _Tp = int, _HashFcn = HashStringFactor, _EqualKey = EqStringFactor, _Alloc = std::allocator<int>]
    make: *** [buildSGIHash.o] Erreur 1
    Du coup, je serais tent� de mettre un hash_kmer[factor.c_str] � la place de mon hash_kmer[factor], mais je ne vois plus vraiment l'int�r�t. Donc, avant de faire trop de b�tises (d�j� que j'ai chang� pas mal ton code), je vais attendre de me faire calmer par un expert

    PS : Je peux envoyer tout le code, si jamais �a peut aider...

  20. #20
    screetch
    Invit�(e)
    Par d�faut
    dans ton code:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    StringFactor::StringFactor(const char *string, uint pos, uint kmer_length) {
      m_factor = new char[kmer_length+1]; // +1 pour le 0 terminal
      strncpy(m_factor, string.substr(pos,kmer_length),kmer_length);
    }
     
    ~StringFactor()::StringFactor(){
      delete [] m_factor;
    }
    m_factor a une taille fixe (kmer_length + 1) et kmer est petit (25?).
    Du coup allouer avec new ca a peu d'interet. Il vaut mieux le mettre comme un tableau (char m_factor[kmer_length])

    ensuite, substr() cr�e une allocation aussi, c'est ce que j'essayais d'�viter.
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
      strncpy(m_factor, string.substr(pos,kmer_length),kmer_length);
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
      strncpy(m_factor, string.c_str() + pos, kmer_length);
    est bien plus efficace car il ne cr�e pas un string temporaire, donc �vite une allocation


    Pour le hash, c'est parce que le hashmap attend un hash sur StringFactor. Or toi tu lui donnes un hash capable de hasher les char*, ce n'est pas le m�me type. C'est pour ca que j'ai ajout� un operator() qui sait comment hasher les StringFactor (note qu'en fait il ne sait pas hasher, mais il sait demander au hash<const char *> de faire le boulot)

    pour ton erreur, c'est la seule que tu as? car je vois que non seulement ton hash ne marcherait pas normalement, mais en plus que
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    strncpy(m_factor, string.substr(pos,kmer_length),kmer_length);
    n'est pas cens� compiler.

    a priori je vois pas; reposter le code aiderait

+ R�pondre � la discussion
Cette discussion est r�solue.
Page 1 sur 2 12 Derni�reDerni�re

Discussions similaires

  1. STL Probl�me avec une liste d'instances de class
    Par BruceBoc dans le forum SL & STL
    R�ponses: 12
    Dernier message: 16/02/2007, 14h12
  2. [JBOSS] [Struts] Probl�me avec une application
    Par Tiercel dans le forum Wildfly/JBoss
    R�ponses: 5
    Dernier message: 13/07/2004, 13h50
  3. Probl�me avec une instruction OUTER /Postgres
    Par Volcomix dans le forum Langage SQL
    R�ponses: 14
    Dernier message: 21/04/2004, 16h56
  4. probl�me avec une requ�te imbriqu�e
    Par jaimepasteevy dans le forum Langage SQL
    R�ponses: 13
    Dernier message: 05/12/2003, 10h29
  5. Probl�me avec une proc�dure stock�e
    Par in dans le forum Langage SQL
    R�ponses: 4
    Dernier message: 27/05/2003, 15h33

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