2009-02-24 7 views
3

J'ai fait face à une chose assez étrange liée à stdext hashmap. Je dois travailler avec beaucoup d'objets et c'est une priorité d'accéder rapidement aux éléments. Mon programme lit les valeurs d'objet d'un fichier et s'il s'agit d'un nouvel élément, insérez cette valeur dans un hashmap, s'il s'agit d'un objet déjà traité, puis change la valeur stockée dans hashmap.C++ stdext hashmap efficiency - réorganisation (?)

Mon problème est lié à hashmap(stdext). Je n'ai trouvé aucune option d'initialisation pour ce conteneur.

L'élément clé est un entier non signé (uint64), et cet objet est stocké dans le hashmap avec cette clé, avec une taille de 160 Ko.
Le programme fonctionne, mais je dois attendre trop, lorsque le nombre d'objets dans hashmap atteint une limite.

Ensuite, le hashmap fonctionne à nouveau correctement, comme je le souhaite. J'ai pensé que c'était peut-être une étape de réorganisation.

Mais ces étapes sont critiques, car après un certain nombre d'objets, il faut 5 heures pour que cette étape soit effectuée, alors qu'une étape de traitement normale dure environ 2-3 minutes. Après cela, le traitement devient "normal".

Est-ce que quelqu'un a fait face à de tels problèmes? Est-ce que quelqu'un sait quelque chose de plus profond à propos de cette hashmap? Je n'ai trouvé rien de pertinent lié à ce sujet.


Je suis en train d'utiliser les paramètres de HashMap avec des valeurs non définies par défaut: le bucket_size et min_buckets. Les valeurs par défaut sont bucket_size=4 et min_buckets=8. Je les ai changés dans le fichier xhash à des valeurs plus grandes, parce que je n'ai pas réussi à changer ces valeurs du code. Je pense que min_buckets est critique dans mon application, j'essaie de "finetune" pour obtenir une meilleure performance en évitant l'étape de réorganisation.

Mais alors j'ai un autre problème, tout fonctionne bien jusqu'à ce que j'essaie d'effacer le hashmap. Ça prend beaucoup de temps. Quand je l'utilise avec les valeurs par défaut, ça marche très vite.

Était-ce une mauvaise action de changer le fichier xhash? Quelqu'un a-t-il déjà utilisé des valeurs autres que des valeurs par défaut? Quelles sont les raisons de cette lenteur?

Ma deuxième question concerne le stockage de pointeurs dans hashmap. L'idée est claire, mais comment pourrais-je réussir à libérer la mémoire pointue. Je devrais créer des pointeurs sur mes objets; ces pointeurs sont stockés dans hashmap et quand j'ai besoin de la valeur je peux l'avoir déréférencer ce pointeur. Mais comment pourrais-je effacer la mémoire après avoir sauvegardé la carte? Peut-être que c'est une question triviale, mais maintenant je ne vois pas la solution.

Merci pour vos réponses déjà postées.

Répondre

3

La copie de votre objet est probablement très coûteuse (compte tenu de sa taille). Essayez de stocker un pointeur sur l'objet au lieu de tout, ou un boost :: shared_ptr si vous voulez simplifier la suppression. De cette façon, lorsque la structure de données se réorganise, la copie est très rapide, puisqu'il s'agit juste d'une affectation de pointeur, au lieu de tout ce qui était nécessaire pour copier votre énorme objet.

0

On dirait que vous êtes touché par le coût de la copie de vos objets lorsque le conteneur décide d'allouer de la place pour plus d'objets.Les deux options les plus simples sont les suivantes:

  1. Si vous connaissez le nombre d'objets que vous serez en insérant en utilisant la fonction void resize(size_type n).

  2. Vous pouvez stocker des pointeurs dans le conteneur plutôt que les objets eux-mêmes.

+0

La fonction de redimensionnement sonne bien, mais le compilateur ne l'aime pas, car "'redimensionner': n'est pas membre de 'stdext :: hash_map <_Kty,_Ty>'". Voulez-vous dire, que je devrais l'utiliser de la manière suivante: par exemple: hashmap0.resize (100) –

+0

L'implémentation hash_map de Dinkumware n'a pas de membre de redimensionnement. Vous ne savez pas si unordered_map de TR1 le fera - Andrew aurait pu faire référence à cela? IIRC Vous pouvez le construire avec une struct pour l'un de ses paramètres de template qui décrit sa taille initiale. – Peter

0

Votre problème est celui de la réallocation (et de la copie) ou de la collision de hachage.

Les vecteurs en souffrent trop (et leur taille d'allocation augmente de façon exponentielle). Cependant, les cartes, les ensembles et les hashmaps sont généralement moins affectés. Ces dernières classes n'ont pas de membre resize() dans la plupart des cas. Ainsi,

  • Vous pouvez passer un allocateur personnalisé (que la plupart des conteneurs permettent AFAIK)
  • Choisissez un meilleur algorithme de hachage

Vous pouvez, si vous le souhaitez, vérifiez avec votre mise en œuvre de hashmap à voyez s'ils suivent l'idiome du mouvement. S'ils ne le font pas.

0

Utilisez Java. Vous serez choqué par l'ordre par lequel il bat C++ quand il s'agit d'insertions de carte de hachage efficaces (meilleurs allocateurs, pas de copie) et le fait correspondre aux recherches.

Questions connexes