Leistungsstarke Implementierung von C++-Hashtabellen

std::unordered_mapist mir zu langsam. Ich will etwas schnelleres! Welche Bibliotheken/eigenständigen Quellen implementieren alternative, schnellere Hash-Maps mit einer ähnlichen (oder überlegenen) Schnittstelle?

Anforderungen:

  • Kostenlos
  • Gratis
  • Eine Art Test, um Behauptungen über die Effizienz zu untermauern
  • Nicht zu vernachlässigende Benutzerbasis

Antworten (4)

Himmel und Hölle

  • Formular: Nur Kopfzeile
  • Lizenz: MIT (kostenlos und kostenlos)
  • Ergebnisse der Leistungsbenchmarks: hier
  • Git-Repository: tessil/hopscotch-map

Hopscotch ist auch ziemlich leistungsfähig. Ich habe es gefunden, als ich nach etwas Ähnlichem gesucht habe. Ich habe bisher einmal ein kleineres Projekt verwendet, bei dem es eine weitaus bessere Leistung hatte als std::unordered_map. Leistungstests im Vergleich zu den anderen Konkurrenten habe ich nicht durchgeführt.

Die reine Header-Bibliothek ist auf GitHub unter dem obigen Link verfügbar. Die Bibliothek bietet auch Implementierungen anderer Hash-Map-Algorithmen. Der Ersteller behauptet, dass es weniger Speicher verbraucht als Google, dense_hash_mapaber eine ähnliche Leistung hat. Aber wie Sie aus anderen Beiträgen hier sehen können, tauchen ziemlich kontinuierlich neue Hash-Map-Implementierungen auf. Laut einem Beitrag, den ich gelesen habe, soll Hopscotch schneller sein als die ska::flat_hash_map. Auf jeden Fall ist es viel schneller als die Karten in std.

Können Sie beschreiben, was daran besonders ist? Wer hat es entwickelt? Was ist die Motivation/der Kontext für seine Entwicklung? Warum heißt es so?
fügte einige weitere Details hinzu, die ich auf einen schnellen Blick finden und an die ich mich erinnern konnte, wenn ich es benutzte.

Wenn Sie Garantien wie Referenzstabilität opfern können, können Sie verwenden

ska::flat_hash_mapvon Malte Skarupke

Die Hauptmerkmale sind:


Auf YouTube gibt es dazu auch einen Vortrag von Malte Skarupke bei C++ Now 2018:

Sie können Besseres tun als std::unordered_map: Neue Verbesserungen der Leistung von Hash-Tabellen

und Blogposts in seinem persönlichen Blog, wo Sie auch das Benchmark-Bild unten finden können:

Geben Sie hier die Bildbeschreibung ein

1. Bitte schreiben Sie ein paar Sätze darüber, was das Besondere an dieser Hash-Map-Implementierung ist oder was ihre wichtigsten Designmerkmale sind; Links sind nett, aber die allgemeine Richtlinie bei StackExchange ist, dass die grundlegenden Informationen in der Antwort enthalten sind. 2. Es gibt drei verschiedene Kartenüberschriften unter dem Link - wie hängen sie zusammen?
@einpoklum Ich habe diesem Beitrag die im Blog aufgeführten Hauptfunktionen hinzugefügt. Ich glaube nicht, dass es machbar ist, einen Vortrag von 1 Stunde 30 Minuten in ein paar Sätzen zusammenzufassen. Nur der flat_hash_map.hppHeader ist wichtig, ich habe den Link geändert.

Es gibt eine Hash-Table-Shootout- Seite auf incise.org.

Demnach ist die beste Leistung – in Bezug auf Geschwindigkeit, nicht Speicher – mit Googles Dense Hash Map: C++11 repository , original repository .

Hinweis: Die verknüpften Repositories heißen "sparsehash", enthalten aber tatsächlich sowohl die Sparse- als auch die Dense-Hash-Maps sowie die Sparse- und Dense-Hash-Sets.

Der Test ist 8 Jahre alt - es könnte sich lohnen, die Zahlen mit aktuellem GCC erneut zu überprüfen.
In meinen neueren Tests ist es genauso schnell oder schneller als ska::flat_hash_map und F14 und sowohl F14 als auch google dense sind speichereffizienter als ska::flat_hash_map: 1ykos.github.io/patchmap/#Performance%20comparison
@WolfgangBrehm: Was meinst du mit "es"? Ich habe "Patchmap" in meiner Antwort nicht erwähnt ... vielleicht könnten Sie eine separate Antwort über Ihre Arbeit schreiben?
@einpoklum Ich denke darüber nach, deshalb bin ich hier, aber es ist nicht wirklich das schnellste haha. Aber ich habe Benchmarks erstellt, die Patchmap, Google Dense, F14, ska::flat_hash_map und viele mehr vergleichen, die Sie finden können, wenn Sie dem Link folgen. Die schnellsten Hash-Tabellen haben die niedrigsten Punkte, die speichereffizientesten rechts.
@WolfgangBrehm: Es muss nicht der schnellste sein. Die Frage betrifft schnellere Hash-Maps als std::unordered_map. Wenn es interessant ist, und es scheint so zu sein, verdient es eine Antwort und wahrscheinlich eine positive Bewertung.
@einpoklum Vielen Dank, dass Sie mich motiviert haben, eine Empfehlung hinzuzufügen, aber was Sie wahrscheinlich wirklich wollen, ist absl::flat_hash_map , das schnellste mit einer tatsächlichen Benutzerbasis. Soll ich dazu auch noch einen Post machen?
@WolfgangBrehm Ja. Obwohl - sind Sie sicher, dass es sich nicht um eine "Neufassung" der älteren Google Dense Hash Map handelt?

Patchkarte

  • Open Source
  • kostenlose Unterstützung von mir
  • umfangreiche Leistungstests und spärliche Unit-Tests
  • fast perfekt imitiert die Schnittstelle vonstd::unordered_map
  • Offene Adressierung mit linearer Sondierung mit Pseudozufallsreihenfolge (ähnlich Robin-Hood-Hashing)

Ich hatte ein ähnliches Problem, ich brauche eine Hash-Tabelle, die nicht nur schneller, sondern auch speichereffizienter ist, deshalb habe ich die Patchmap erstellt. Die relevanteste Statistik bei der Beurteilung der Leistung einer Hash-Tabelle ist der Raum-Zeit-Kompromiss. Sowohl Zeit als auch Speicher sind kostspielige Ressourcen, also sollten Sie sie sparen, aber der bevorzugte Kompromiss kann unterschiedlich sein.Suchleistung und Speichernutzung verschiedener Hash-Tabellen

patchmap: 🔴                khash: × 
bytell: +                   google::sparse_hash_map: ○ 
google::dense_hash_map: ⬟   ska::flat_hash_map: △ 
std::unordered_map: ◇       sparsepp: ◻     
Judy array: ◆               F14ValueMap: ▲ 
chaining+sorting: •         robin_hood::unordered_map: ▽  
absl::flat_hash_map: ⬠      tsl::sparse_hash_map: ★ 
emilib2::HashMap: ▩ 

Erfolgreiche Lookups sind wahrscheinlich die am weitesten verbreitete Operation, die eine Hash-Tabelle ausführen muss, aber Einfügen, Löschen und fehlgeschlagene Lookup- Benchmarks ändern das Bild nicht dramatisch. Die Patchmap ist nicht die schnellste. Am schnellsten wäre eine Hash-Tabelle mit viel Speicher, einem schnellen und guten Hash und einem einfachen offenen Adressierungs- und Sondierungsschema wie linearer Sondierung. Es ist auch nicht das speichereffizienteste, obwohl die Pseudozufallsreihenfolge auf dieses Regime gebracht werden kann, wodurch die Geschwindigkeit geopfert wird. Es bietet jedoch ein kleines Produkt aus Raum und Zeit, gleichauf mit bytell , beide nur unwesentlich besser als absl::flat_hash_map .

Das ist eine ziemlich informative Tabelle :-)