web-dev-qa-db-fra.com

Carte de hachage C / C ++ ultra haute performance (tableau, dictionnaire)

J'ai besoin de mapper des clés primitives (int, peut-être longues) pour structurer des valeurs dans une structure de données de carte de hachage haute performance.

Mon programme aura quelques centaines de ces cartes, et chaque carte aura généralement au plus quelques milliers d'entrées. Cependant, les cartes seront "rafraîchissantes" ou "baratteuses" en permanence; imaginez traiter des millions de add et delete messages par seconde.

Quelles bibliothèques en C ou C++ ont une structure de données adaptée à ce cas d'utilisation? Ou, comment recommanderiez-vous de construire le vôtre? Merci!

77
Haywood Jablomey

Je vous recommande d'essayer Google SparseHash (ou la version C11 Google SparseHash-c11 ) et de voir si cela convient à vos besoins. Ils ont une implémentation efficace en mémoire ainsi qu'une optimisée pour la vitesse. J'ai fait un benchmark il y a longtemps, c'était la meilleure implémentation de table de hachage disponible en termes de vitesse (mais avec des inconvénients).

30
Scharron

Quelles bibliothèques en C ou C++ ont une structure de données adaptée à ce cas d'utilisation? Ou, comment recommanderiez-vous de construire le vôtre? Merci!

Découvrez le LGPL'd tableaux Judy . Je ne me suis jamais utilisé, mais il m'a été annoncé à quelques reprises.

Vous pouvez également essayer de comparer les conteneurs STL (std :: hash_map, etc.). Selon la plate-forme/l'implémentation et le réglage du code source (préallouer autant que vous le pouvez, la gestion dynamique de la mémoire coûte cher), ils pourraient être assez performants.

De plus, si les performances de la solution finale l'emportent sur le coût de la solution, vous pouvez essayer de commander le système avec suffisamment de RAM pour tout mettre en tableaux simples. Les performances d'accès par index sont imbattables.

Les opérations d'ajout/suppression sont beaucoup (100x) plus fréquentes que l'opération get.

Cela indique que vous voudrez peut-être vous concentrer d'abord sur l'amélioration des algorithmes. Si les données sont seulement écrites, pas lues, alors pourquoi les écrire du tout?

11
Dummy00001

Utilisez simplement boost::unordered_map (ou tr1 etc) par défaut. Ensuite, profilez votre code et voyez si ce code est le goulot d'étranglement. Ce n'est qu'alors que je proposerais d'analyser précisément vos besoins pour trouver un substitut plus rapide.

11
Mark B

Si vous avez un programme multithread, vous pouvez trouver des tables de hachage utiles dans la bibliothèque de blocs de construction de threads Intel . Par exemple, tbb :: concurrent_unordered_map a la même api que std :: unordered_map, mais ses fonctions principales sont thread-safe.

Jetez également un œil à la bibliothèque de folie de Facebook , elle possède une table de hachage concurrente à hautes performances et sauter la liste .

6
Pavel Davydov

khash est très efficace. Il y a un benchmark détaillé de l'auteur: https://attractivechaos.wordpress.com/2008/10/07/another-look-at-my-old-benchmark/ et il montre aussi khash bat beaucoup d'autres hash bibliothèques.

3
zhanxw

depuis Android sources (donc Apache 2 sous licence)

https://github.com/CyanogenMod/Android_system_core/tree/ics/libcutils

regardez hashmap.c, choisissez include/cutils/hashmap.h, si vous n'avez pas besoin de sécurité des threads, vous pouvez supprimer le code mutex, un exemple d'implémentation est dans libcutils/str_parms.c

3
sherpya

Vérifiez d'abord si les solutions existantes comme libmemcache correspondent à vos besoins.

Si non ...

Les cartes de hachage semblent être la réponse définitive à votre besoin. Il fournit o(1) recherche basée sur les clés. La plupart des bibliothèques STL fournissent une sorte de hachage de nos jours. Utilisez donc celui fourni par votre plate-forme.

Une fois cette partie terminée, vous devez tester la solution pour voir si l'algorithme de hachage par défaut est suffisamment performant pour vos besoins.

Si ce n'est pas le cas, vous devriez explorer quelques bons algorithmes de hachage rapide trouvés sur le net

  1. bon vieux nombre premier multiplier algo
  2. http://www.azillionmonkeys.com/qed/hash.html
  3. http://burtleburtle.net/bob/
  4. http://code.google.com/p/google-sparsehash/

Si cela ne suffit pas, vous pouvez lancer vous-même un module de hachage, qui résout le problème que vous avez vu avec les conteneurs STL que vous avez testés et l'un des algorithmes de hachage ci-dessus. Assurez-vous de publier les résultats quelque part.

Oh et c'est intéressant que vous ayez plusieurs cartes ... peut-être pouvez-vous simplifier en ayant votre clé sous forme de nombre 64 bits avec les bits élevés utilisés pour distinguer à quelle carte elle appartient et ajouter toutes les paires de valeurs de clés à un hachage géant. J'ai vu des hachages contenant des centaines de milliers de symboles fonctionnant parfaitement bien sur l'algorithme de hachage de nombre premier de base.

Vous pouvez vérifier les performances de cette solution par rapport à des centaines de cartes. Je pense que cela pourrait être mieux du point de vue du profilage de la mémoire ... veuillez publier les résultats quelque part si vous arrivez à faire cet exercice

Je crois que plus que l'algorithme de hachage, ce pourrait être l'ajout/suppression constant de mémoire (peut-il être évité?) Et le profil d'utilisation du cache du processeur qui pourraient être plus cruciaux pour les performances de votre application

bonne chance

2
computinglife

Je suggère thash . Incluez simplement #include "uthash.h" puis ajoutez un UT_hash_handle à la structure et choisissez un ou plusieurs champs dans votre structure pour agir comme clé. Un mot sur les performances ici .

2
sjain

Essayez les tables de hachage de Modèles de conteneurs divers . Son closed_hash_map est à peu près à la même vitesse que Google dense_hash_map, mais il est plus facile à utiliser (aucune restriction sur les valeurs contenues) et a également d'autres avantages.

2
doublep

http://incise.org/hash-table-benchmarks.html gcc a une très très bonne implémentation. Cependant, sachez qu'elle doit respecter une très mauvaise décision standard:

Si une refonte se produit, tous les itérateurs sont invalidés, mais les références et pointeurs vers des éléments individuels restent valides. Si aucun remaniement réel ne se produit, aucun changement.

http://www.cplusplus.com/reference/unordered_map/unordered_map/rehash/

Cela signifie essentiellement que la norme dit que la mise en œuvre DOIT ÊTRE basée sur des listes liées. Il empêche l'adressage ouvert qui a de meilleures performances.

Je pense que Google clairsemé utilise l'adressage ouvert, bien que dans ces benchmarks, seule la version dense surpasse la concurrence. Cependant, la version clairsemée surpasse toute concurrence dans l'utilisation de la mémoire. (il n'a pas non plus de plateau, pure ligne droite par rapport au nombre d'éléments)

1
v.oddou