I filtri bloom sono effettivamente più veloci degli hash, anche prendendo in considerazione la cache dell'account?


16

I filtri Bloom sembrano davvero fantastici se si considera che è possibile determinare se un Int è in un set con una certezza del 99% a tempo costante. Ma anche gli hash possono farlo, con l'unica differenza che, in un hash, la maggior parte delle volte accedi alla memoria solo una volta. Con i filtri bloom, è necessario accedervi ~ 7 volte per richiesta in luoghi completamente distanti , in modo da avere diversi errori di cache per richiesta.

Mi sto perdendo qualcosa?


Quali luoghi completamente distanti? Ci sono solo m bit. Probabilmente si adatta a un singolo registro o, nel peggiore dei casi, a una singola riga della cache.

1
@delnan AFAIK usa qualcosa di circa 10 bit / elemento, no? Quindi, per diverse migliaia di elementi - ovvero enormi archivi di dati - sicuramente non si adatta a una cache. Pertanto, se si utilizzano khash, probabilmente si verificano errori di kcache per lettura. Le tabelle hash, d'altra parte, garantiscono che la maggior parte delle volte avrai la tua risposta con 0 cache cache - le collisioni sono comunque rare.
MaiaVictor,

Hai k bit, punto. Tutti gli elementi influenzano lo stesso numero fisso di bit, ecco perché la percentuale di falsi positivi dipende dal numero di voci.

Risposte:


33

Manca il modo in cui le due strutture dati gestiscono le collisioni di hash. I filtri bloom non memorizzano i valori effettivi, quindi lo spazio richiesto è la dimensione costante dell'array designato. Invece, se usi un hash tradizionale, cerca di memorizzare tutti i valori che gli dai, quindi cresce con il tempo.

Considera una funzione hash semplificata (solo a scopo di esempio!) f(x) = x % 2. Ora è in ingresso i seguenti numeri interi: 2, 3, 4, 5, 6, 7.

Hash standard: i valori indicati verranno sottoposti a hash e finiremo con molte collisioni dovute a f(2) = f(4) = f(6) = 0e f(3) = f(5) = f(7) = 1. Tuttavia, l'hash memorizza tutti questi valori e sarà in grado di dirti che 8non è memorizzato in esso. Come lo fa? Tiene traccia delle collisioni e memorizza tutti i valori con lo stesso valore hash, quindi quando lo interroghi, confronta ulteriormente la tua query. Quindi interroghiamo la mappa per 8:, f(8) = 0quindi esamineremo un bucket in cui abbiamo già inserito 2, 4, 6e dobbiamo fare 3 confronti per dirti che 8non faceva parte dell'input.

Filtro Bloom: normalmente, ciascun valore di input viene sottoposto a hash rispetto a kdiverse funzioni hash. Ancora una volta, per semplicità, supponiamo che usiamo solo la singola funzione hash f. Abbiamo quindi bisogno di un array di 2 valori e quando incontriamo l'input 2significa che a causa di f(2) = 0impostare il valore dell'array in posizione 0sul valore 1. Lo stesso succede per 4e 6. Allo stesso modo, gli input 3, 5, 7impostano ciascuno la posizione dell'array 1su value 1. Ora chiediamo se 8faceva parte dell'input: f(8) = 0e l'array in posizione lo 0è 1, quindi il filtro bloom affermerà erroneamente che 8era effettivamente parte dell'input.

Per diventare un po 'più realistici, consideriamo che aggiungiamo una seconda funzione hash g(x) = x % 10. Con ciò, il valore di ingresso 2porta a due valori hash f(2) = 0e g(2) = 2e due corrispondenti posizioni di matrice vengono impostati 1. Ovviamente, l'array ora dovrebbe essere almeno di dimensioni 10. Ma quando eseguiamo una query 8, verificheremo l'array nella posizione 8dovuta g(8) = 8e tale posizione rimarrà comunque 0. Ecco perché ulteriori funzioni hash riducono i falsi positivi che otterrai.

Confronto: il filtro bloom utilizza kfunzioni hash, il che significa che ksi accede a posizioni casuali dell'array. Ma quella cifra è esatta. L'hash invece ti garantisce solo un tempo di accesso costante ammortizzato, ma può de-generare in base alla natura della funzione hash e ai dati di input. Quindi è in genere più veloce, ad eccezione dei casi non generati.

Tuttavia, una volta che si verifica una collisione dell'hash, l'hash standard dovrà verificare l'uguaglianza dei valori memorizzati rispetto al valore della query. Questo controllo di uguaglianza può essere arbitrariamente costoso e non si verificherà mai con un filtro di fioritura.

In termini di spazio, il filtro bloom è costante, in quanto non è mai necessario utilizzare più memoria dell'array designato. D'altra parte, l'hash cresce dinamicamente e può diventare molto più grande a causa della necessità di tenere traccia dei valori di collisione.

Trade-off: ora che sai cosa costa poco e cosa no e in quali circostanze, dovresti essere in grado di vedere il trade-off. I filtri Bloom sono fantastici se vuoi rilevare molto rapidamente che un valore è stato visto in precedenza, ma può vivere con falsi positivi. D'altra parte, puoi scegliere la mappa hash se desideri la correttezza garantita al prezzo di non poter giudicare esattamente il tuo tempo di esecuzione, ma puoi accettare casi degenerati occasionalmente che potrebbero essere molto più lenti della media.

Allo stesso modo, se ti trovi in ​​un ambiente di memoria limitato, potresti voler preferire i filtri bloom per la loro garanzia di utilizzo della memoria.


Bella risposta. Questo è ciò che stavo confondendo. In realtà ogni struttura di dati ha i suoi migliori casi d'uso e la diversa considerazione dipende dal compromesso.
Richard,

È davvero un'ottima spiegazione con un esempio adeguato. Quindi, come possiamo andare con il valore 'k'? Dipende dal numero totale di valori che abbiamo?
itsraghz,

5

I casi d'uso per filtri e hash bloom sono distinti e per lo più disgiunti, quindi il confronto diretto non ha senso. Inoltre dipenderà dai dettagli tecnici delle implementazioni in quanto vi sono molti modi per gestire le collisioni di hash con diversi compromessi.

Il filtro bloom può rispondere se l'elemento è in un set per enormi set, con ragionevole probabilità, ma non esattamente, usando una modesta quantità di memoria. Enormi trilioni di elementi. Ma non sono mai esatti. Puoi ridurre la quantità di falsi positivi solo usando più memoria o più funzioni hash.

D'altra parte le tabelle hash sono esatte, ma devono memorizzare il set. Quindi trilioni di elementi richiederebbero terrabyte di memoria (e questo è solo trilioni americani). Possono anche memorizzare dati aggiuntivi per ciascun elemento, cosa che i filtri bloom non possono.

Quindi i filtri bloom vengono utilizzati quando si dispone di un metodo lento per ottenere dati per alcuni membri (che coinvolge il server di query, letture dal disco e simili) di un set di grandi dimensioni (che non si adatta alla memoria o non è pratico trasferirli al client o tale) e desidera evitare di eseguire l'operazione lenta per gli oggetti che non si trovano nel set.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.