2010-08-09 2 views
28

A volte è necessario eseguire una funzione hash di un puntatore; non l'oggetto al quale punta il puntatore, ma il puntatore stesso. Un sacco di tempo, gente semplicemente punt e usa il valore del puntatore come un numero intero, tagliando alcuni bit alti per adattarlo, magari spostando i bit dello zero noto in basso. Il fatto è che i valori del puntatore non sono necessariamente ben distribuiti nello spazio del codice; in effetti, se il tuo allocatore sta facendo il suo lavoro, ci sono ottime possibilità che siano tutti raggruppati insieme.Hash dei valori di puntatore

Quindi, la mia domanda è, qualcuno ha sviluppato funzioni hash che fanno bene a questo? Prendi un valore a 32 o 64 bit che abbia forse 12 bit di entropia nello da qualche parte nello e diffondilo uniformemente su uno spazio numerico a 32 bit.

+1

possibile duplicato di [Quale funzione di hash intero è valida che accetta un numero intero di chiave hash?] (Http://stackoverflow.com/questions/664014/what-integer-hash-function-are-good-that-accepts- an-intero-hash-key) –

risposta

20

This page elenca diversi metodi che potrebbero essere utili. Uno di questi, a causa di Knuth, è un semplice come moltiplicando (in 32 bit) per 2654435761, ma "I risultati di hash male vengono prodotti se i tasti variano nei bit superiori." Nel caso dei puntatori, questa è una situazione abbastanza rara.

Here sono altri algoritmi, inclusi test delle prestazioni.

Sembra che le parole magiche siano "hashing intero".

+0

E quando si cerca "hashing intero", si viene puntati su un'altra pagina SO che questa duplica in modo efficace. :-) –

+0

Grazie. Non mi è venuto in mente di cercare "hashing intero" perché ero bloccato sui valori che sono * puntatori *, ma quelle pagine sembrano molto utili. – zwol

+0

Ma su un sistema a 32 bit i bit di indirizzi superiori possono benissimo essere in uso ... –

1

Perché non utilizzare solo uno hash function esistente?

+5

Sospetto che la loro motivazione sia la velocità. –

3

Probabilmente esporranno la località, sì - ma nei bit più bassi, il che significa che gli oggetti saranno distribuiti attraverso l'hashtable. Vedrai solo le collisioni se l'indirizzo di un puntatore è un multiplo della lunghezza della tabella hash da un altro puntatore.

+1

Questa non è la mia intuizione. Mi aspetterei che un tipico puntatore (a 32 bit) nell'heap abbia il formato 'CCCC XXX8' (esadecimale) - alto mezzo costante o quasi, * forse * 12 bit di entropia nella metà bassa, nybble inferiore più vicino - di nuovo costante. E la metà bassa rischia di segnare un numero con un sacco di due nella sua fattorizzazione principale. – zwol

+1

Hai già menzionato lo spostamento dei bit bassi, però. Se ci sono tutti i bit di entropia che ci sono nel numero, nessuna quantità di hashing lo aumenterà, comunque. –

2

Se si conosce l'indirizzo del puntatore più basso possibile (che si verifica spesso se si lavora all'interno di un buffer di grandi dimensioni), basta convertire il puntatore in un numero intero sottraendo il valore di puntatore più basso possibile; per esempio. quello potrebbe essere l'indirizzo di base del buffer. -Ricorda: il puntatore sottratto dal puntatore equivale a un offset (intero). Quindi: non "tagliare" i bit; è molto meglio convertire in offset. Ciò comporterà che il valore di offset è molto più piccolo di un valore di puntatore. In alcuni casi può essere utile spostare ulteriormente il valore del puntatore due volte (ad es. Dividere per 4), prima di eseguirne l'hashing. Il problema con i puntatori è spesso che piccoli blocchi di memoria sono probabilmente allocati sullo stesso indirizzo (ad esempio un blocco viene liberato e un altro blocco sta prendendo il posto del blocco liberato).