Ich möchte eine schnelle, gut verteilte Hash-Tabelle in C # implementieren. Ich habe Probleme bei der Auswahl meiner Hash-Einschränkungsfunktion, die einen beliebigen Hash-Code verwendet und ihn "einschränkt", damit er zum Indizieren der Buckets verwendet werden kann. Bisher sehe ich zwei Möglichkeiten:
Einerseits können Sie sicherstellen, dass Ihre Buckets immer eine Primzahl von Elementen haben, und um den Hash einzuschränken, modulieren Sie ihn einfach durch die Anzahl der Buckets. Dies ist in der Tat das, was das .NET-Wörterbuch tut . Das Problem bei diesem Ansatz ist, dass die Verwendung von% im Vergleich zu anderen Vorgängen extrem langsam ist. Wenn Sie sich die Agner Fog-Befehlstabellen ansehen
idiv
(dies ist der Assembly-Code, der für% generiert wird) , beträgt die Befehlslatenz für neuere Intel-Prozessoren ~ 25 Zyklen. Vergleichen Sie dies mit rund 3 fürmul
oder 1 für bitweise ops wieand
,or
oderxor
.Auf der anderen Seite kann die Anzahl der Buckets immer eine Potenz von 2 sein. Sie müssen immer noch den Modul des Hash berechnen, damit Sie nicht versuchen, außerhalb des Arrays zu indizieren, aber diesmal ist es weniger teuer . Da für Potenzen von 2
% N
gerade ist& (N - 1)
, wird die Beschränkung auf eine Maskierungsoperation reduziert, die nur 1-2 Zyklen dauert. Dies geschieht durch Googles Sparsehash . Der Nachteil dabei ist, dass wir uns darauf verlassen, dass Benutzer gute Hashes bereitstellen. Durch das Maskieren des Hashs wird im Wesentlichen ein Teil des Hashs abgeschnitten, sodass nicht mehr alle Teile des Hashs berücksichtigt werden. Wenn der Hash des Benutzers ungleichmäßig verteilt ist, zum Beispiel nur die höheren Bits ausgefüllt werden oder die niedrigeren Bits konsistent gleich sind, hat dieser Ansatz eine viel höhere Kollisionsrate.
Ich suche nach einem Algorithmus, der das Beste aus beiden Welten bietet: Er berücksichtigt alle Teile des Hashs und ist außerdem schneller als die Verwendung von%. Es muss nicht unbedingt ein Modul sein, sondern etwas, das garantiert im Bereich liegt 0..N-1
(wobei N die Länge der Schaufeln ist) und für alle Schlitze gleichmäßig verteilt ist. Gibt es einen solchen Algorithmus?
Danke fürs Helfen.
(2^N +/- 1)
siehe stackoverflow.com/questions/763137/…