Est un unordered_map vraiment plus rapide qu'une carte dans la pratique?
Sûr, la recherche de la performance d'une unordered_map est constante en moyenne, et la recherche de la performance d'une carte est O(logN).
Mais bien sûr dans le but de trouver un objet dans une unordered_map, nous avons:
- de hachage de la clé que nous voulons trouver.
- equality_compare la clé avec toutes les clés dans le même seau.
Alors que dans une carte, nous avons simplement besoin de less_than comparer les recherchés clé avec log2(N) touches, où N est le nombre d'éléments dans la carte.
Je me demandais ce que la performance réelle différence serait, étant donné que la fonction de hachage ajoute-dessus et un equality_compare est pas moins cher qu'un less_than comparer.
Plutôt que de déranger la communauté avec une question, je peux répondre moi-même, j'ai écrit un test.
J'ai partagé les résultats ci-dessous, au cas où quelqu'un d'autre trouve cela intéressant ou utile.
Plus de réponses sont bien sûr invités si quelqu'un est capable et disposé à ajouter plus d'informations.
map
n'est pas le log N
en soi; c'est que chaque accès à la mémoire que vous marchez dans l'arbre est essentiellement aléatoire. Ce n'est pas important quand la carte est petite, mais elle domine lorsque la carte est grande. (La différence entre l'accès cache et de la mémoire est un ordre de grandeur ou deux; voir par exemple stackoverflow.com/q/4087280. Et cette différence tend à augmenter à travers le CPU générations parce que le physique est local.) Le égal à/inférieur à opérations sont invisibles par rapport au pointeur de la poursuite.Jetez un oeil à mes résultats de tests, en particulier la flat_map vs carte. Il semble à première vue que le pointeur de chasser est de la comptabilité pour un doublement de la recherche du temps dans une carte par rapport à un (grand!) triés vecteur. Cependant, il peut y avoir d'autres facteurs en jeu ici. clang semble plus disposé aux commandes de l'ensemble de la recherche pour
lower_bound
sur un vecteur, que at
pour une carte, par exemple.OriginalL'auteur Richard Hodges | 2016-04-03
Vous devez vous connecter pour publier un commentaire.
En réponse à des questions au sujet de la performance en ce qui concerne le nombre de raté recherches, j'ai refait le test pour la paramétrer.
Exemple de résultats:
Clés:
TL;DR
Résultats: unordered_map montre sa supériorité dès qu'il y a des données dans la carte. Le seul moment où il présente de moins bonnes performances que la commande de la carte, c'est quand les cartes sont vides.
Voici le nouveau code:
OriginalL'auteur Richard Hodges
Dans ce test suivant, j'ai compilé sur apple clang avec-O3, j'ai pris des mesures pour s'assurer que le test est juste, comme:
appeler un évier en fonction du résultat de chaque recherche par le biais d'un vtable, pour empêcher l'utilisation de l'optimiseur de inline loin ensemble des recherches!
exécuter des tests sur 3 différents types de cartes, contenant les mêmes données, dans le même ordre en parallèle. Cela signifie que si un test commence à "prendre de l'avance", il commence à entrer cache-miss territoire pour la recherche (voir le code). Cela signifie que pas de test obtient un avantage injuste d'être confronté à une " hot " de la cache.
paramétrer la taille de la clé (et donc de la complexité)
de paramétrer la taille de la carte
testé trois différents types de cartes (contenant les mêmes données) - un unordered_map, une carte et une triés vecteur de paires clé/valeur.
vérifié l'assembleur de sortie pour s'assurer que l'optimiseur n'a pas été en mesure d'optimiser loin ensemble des morceaux de la logique due à la mort d'analyse de code.
Voici le code:
Résultats:
Comme vous pouvez le voir, le unordered_map de manière convaincante bat la carte et la paire triée vecteur. Le vecteur de paires a deux fois plus rapide que la solution map. C'est intéressant comme lower_bound et map::ont presque l'équivalent de la complexité.
TL;DR
dans ce test, le non-ordonnée de la carte est environ 3 fois plus rapide (pour les recherches) comme un ensemble ordonné de la carte, et un vecteur trié de manière convaincante beats une carte.
En fait j'ai été choqué de voir comment beaucoup plus rapide, il est.
Je fais référence à la modification de la valeur de
nkeys
.Il semble que vos "planisphère" test fait recherche à la fois le vecteur trié et la commande de la carte. Je suis donc un peu surpris de voir que cela a le même calendrier. En fait - qui pourrait avoir à faire avec l'exécution de tests en même temps. Je serais personnellement sentirez mieux si les tests n'ont pas été exécutés simultanément afin d'éliminer la contention comme un facteur, Également, le plat de test de la carte ne devrait pas faire n'importe quoi avec la
ordered
objet (sauf si je suis malentendu quelque chose).re: "le test est tellement rapide qu'il est incommensurable" Le point de l'ensemble de l'examen des ordres de complexité est de comprendre les implications de performances pour différentes valeurs de N. En particulier, l'avantage de la réduction des ordres de complexité, c'est que peu importe comment grand les constant, les frais généraux peuvent être, il y aura un seuil de valeur de N à partir de laquelle l'ordre inférieur de la complexité commence à faire mieux. Dans le but de tester avec de faibles valeurs de N, vous devez répéter l'essai un certain nombre de fois afin d'obtenir des résultats mesurables.
PS: Pour l'enregistrement, vous testez un assez spécifique et probablement d'utilisation anormale modèle: Construire une carte et de recherche de chaque entrée exactement une fois zéro raté recherches. En outre, votre timing exclut le temps nécessaire pour créer les cartes.
OriginalL'auteur Richard Hodges