Chcę zaimplementować szybką, dobrze rozproszoną tabelę skrótów w języku C #. Mam problem z wybraniem funkcji ograniczenia skrótu, która pobiera dowolny kod skrótu i „ogranicza” go, aby można go było użyć do indeksowania segmentów. Do tej pory widzę dwie opcje:
Z jednej strony możesz mieć pewność, że twoje segmenty zawsze mają pierwszą liczbę elementów, a aby ograniczyć hash, po prostu moduluj je według liczby segmentów. Tak właśnie działa Słownik .NET . Problem z tym podejściem polega na tym, że użycie% jest bardzo wolne w porównaniu do innych operacji; jeśli spojrzeć na stołach instrukcji Agner przeciwmgłowe ,
idiv
(który jest kod zespół, który zostanie wygenerowany dla%) ma opóźnienia instrukcji o ~ 25 cykli dla nowszych procesorów Intel. Porównaj to do około 3 domul
lub od 1 do OPS bitowe jakand
,or
lubxor
.Z drugiej strony, możesz zawsze mieć liczbę segmentów o wartości 2. Wciąż będziesz musiał obliczyć moduł skrótu, aby nie próbować indeksować poza tablicą, ale tym razem będzie on tańszy . Ponieważ dla mocy 2
% N
jest po prostu& (N - 1)
ograniczenie jest ograniczone do operacji maskowania, która zajmuje tylko 1-2 cykle. Odbywa się to przez Google Sparsehash . Wadą tego jest to, że liczymy na to, że użytkownicy zapewnią porządny skrót; maskowanie skrótu zasadniczo odcina część skrótu, więc nie uwzględniamy już wszystkich jego fragmentów. Jeśli skrót użytkownika jest nierównomiernie rozłożony, na przykład wypełniane są tylko wyższe bity lub niższe bity są niezmiennie takie same, wówczas podejście to ma znacznie większą częstotliwość kolizji.
Szukam algorytmu, którego mogę użyć, który ma to, co najlepsze z obu światów: bierze pod uwagę wszystkie części skrótu, a także jest szybszy niż użycie%. Nie musi to być moduł, tylko coś, co gwarantuje, że będzie w zakresie 0..N-1
(gdzie N jest długością segmentów) i ma równomierny rozkład dla wszystkich gniazd. Czy taki algorytm istnieje?
Dzięki za pomoc.
(2^N +/- 1)
, patrz stackoverflow.com/questions/763137/…