Sto cercando di implementare una tabella hash veloce e ben distribuita in C #. Ho difficoltà a scegliere la mia funzione di vincolo hash che accetta un codice hash arbitrario e lo "vincola" in modo che possa essere utilizzato per indicizzare i bucket. Ci sono due opzioni che vedo finora:
Da un lato, puoi assicurarti che i tuoi bucket abbiano sempre un numero primo di elementi e, per vincolare l'hash, devi semplicemente modellarlo con il numero di bucket. Questo è, in effetti, ciò che fa il dizionario .NET . Il problema con questo approccio è che l'utilizzo di% è estremamente lento rispetto ad altre operazioni; se si guardano le tabelle di istruzioni della nebbia di Agner ,
idiv
(che è il codice assembly che viene generato per%) ha una latenza di istruzione di ~ 25 cicli per i nuovi processori Intel. Confrontare questo a circa il 3 permul
, o 1 per ops bit per bit comeand
,or
oxor
.D'altra parte, puoi avere il numero di bucket sempre una potenza di 2. Dovrai comunque calcolare il modulo dell'hash in modo da non tentare di indicizzare all'esterno dell'array, ma questa volta sarà meno costoso . Poiché per potenze di 2
% N
è giusto& (N - 1)
, il vincolo si riduce a un'operazione di mascheramento che richiede solo 1-2 cicli. Questo è fatto da Google Sparsehash . L'aspetto negativo di questo è che contiamo sugli utenti per fornire buoni hash; il mascheramento dell'hash essenzialmente interrompe parte dell'hash, quindi non stiamo più prendendo in considerazione tutti i bit dell'hash. Se l'hash dell'utente viene distribuito in modo non uniforme, ad esempio vengono compilati solo i bit più alti o i bit più bassi sono sempre gli stessi, questo approccio ha un tasso di collisioni molto più elevato.
Sto cercando un algoritmo che posso usare che abbia il meglio di entrambi i mondi: prende in considerazione tutti i bit dell'hash ed è anche più veloce dell'uso di%. Non deve necessariamente essere un modulo, solo qualcosa che è garantito essere nella gamma 0..N-1
(dove N è la lunghezza dei bucket) e ha una distribuzione uniforme per tutti gli slot. Esiste un tale algoritmo?
Grazie dell'aiuto.
(2^N +/- 1)
, vedere stackoverflow.com/questions/763137/...