Je viens de commencer à développer un petit utilitaire me permettant de tester les différentes fonctions de hachage de Cuckoo
J'y implémenté le filtre de Cuckoo qui utilise 2 fonctions de hachages int h1( int k, int modulo ) et h2( int k, int modulo ) afin de trouver en quasi temps constant si une entrée y est ou pas
J'ai y très légèrement modifié les fonctions de hachage h1() et h2() afin de pouvoir y gérer les nombres négatifs :
(les fonctions originales sont identiques hormis la suppression du if/else et l'inversion de la valeur de k si elle est négative)
Code c : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 int cuckoo_hash1( int k, int modulo ) { // return k % modulo; if ( k >= 0 ) return k % modulo; else return -k % modulo; } int cuckoo_hash2( int k , int modulo ) { // return ( k / modulo ) % modulo; if ( k >= 0 ) return ( k / modulo) % modulo; else return ( -k / modulo ) % modulo; }
J'y ai de plus mis en place un système permettant d'associer différentes fonctions de hachage possibles h1() et h2() entre elles pour en faire un banc de filtres
Code c : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 int cuckoo_hash0( int k, int modulo ) { return k & modulo; } void cuckoo_hash_func( int rang, HashFunc func ) { HashFuncs[rang] = func; } void cuckoo_init_hash_funcs0() { cuckoo_hash_func(1, cuckoo_hash0); nHashFuncs = 1; } void cuckoo_init_hash_funcs1() { cuckoo_hash_func(1, cuckoo_hash1); cuckoo_hash_func(2, cuckoo_hash2); nHashFuncs = 2; } void cuckoo_init_hash_funcs2() { cuckoo_hash_func(1, cuckoo_hash2); cuckoo_hash_func(2, cuckoo_hash1); nHashFuncs = 2; } void cuckoo_init_hash_funcs() { switch( HashType ) { case HASH_FUNCS_DEFAULT : cuckoo_init_hash_funcs0(); break; case HASH_FUNCS_MODULO : cuckoo_init_hash_funcs1(); break; case HASH_FUNCS_DIVIDE : cuckoo_init_hash_funcs2(); break; } }
=> d'après ce que j'ai trouvé sur le Net, les valeurs de modulo les plus utilisées sont 11 et 31 mais j'ai très agréablement été surpris par la combinaison de la valeur de modulo = 9 et le banc de filtre HASH_FUNCS_DIVIDE :
( HASH_FUNCS_MODULO est le filtre de Cuckoo classique, le filtre HASH_FUNCS_DIVIDE étant tout simplement la permutation des fonctions h1() et h2() dans le banc de 2 fonctions de hachage utilisées par le filtre de Cuckoo)
1) cette combinaison semble bien fonctionner tant avec des valeurs décimales avec des puissances en base 10
Code x : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 yannoo@Thinkoo:~/Dev/Cuckoo$ ./cuckoo 1 10 100 1000 10000 100000 Cuckoo v0.2 by Cylone cuckoo_insert(1) cuckoo_insert(10) cuckoo_insert(100) cuckoo_insert(1000) cuckoo_insert(10000) cuckoo_insert(100000) key T1 T2 === === === 0 1 1 10 2 100 3 1000 4 10000 5 100000 6 7 8 key T3 === === 6 entries cached on T1[] , 0 entries cached on T2[] and 0 entries in T3[] 6 / 6 = 100% insertions OK :) load factor = 6 / 18 = 33% extension factor = 0 / 18 = 0% extended
2) qu'avec des valeurs de puissances en base 2 :
Code x : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 yannoo@Thinkoo:~/Dev/Cuckoo$ ./cuckoo 1 2 4 8 16 32 64 128 256 512 1024 2048 Cuckoo v0.2 by Cylone cuckoo_insert(1) cuckoo_insert(2) cuckoo_insert(4) cuckoo_insert(8) cuckoo_insert(16) cuckoo_insert(32) cuckoo_insert(64) cuckoo_insert(128) cuckoo_insert(256) cuckoo_insert(512) cuckoo_insert(1024) cuckoo_insert(2048) key T1 T2 === === === 0 4 1 16 1 2 512 2 3 32 4 256 5 128 2048 6 7 64 1024 8 8 key T3 === === 6 entries cached on T1[] , 6 entries cached on T2[] and 0 entries in T3[] 12 / 12 = 100% insertions OK :) load factor = 12 / 18 = 67% extension factor = 0 / 18 = 0% extended
=> les entrées sont hyper bien triées dans le cas de l'utilisation puissances de 10 **ET** sont étonnamment toutes présentes les tableaux T1 et T2, bien qu'y étant néanmoins très dispersées
Le tableau T3 permet quand à lui de stocker les valeurs qui ne peuvent être stockées dans les tableaux T1[] ou T2[], du fait de leurs très petite taille qui ne permet pas d'y stocker beaucoup d'entrées, soit 2 x 9 = 18 valeurs au grand maximum avec l'utilisation de modulo 9 et le facteur de remplissage variant entre 0 et 1 tournant aux alentours de 0.5 = 50% en moyenne (de 33% à 72% dans ces exemples) , comme par exemple ici avec 17 premières puissances de 2 :
Code x : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 yannoo@Thinkoo:~/Dev/Cuckoo$ ./cuckoo 1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 65536 Cuckoo v0.2 by Cylone cuckoo_insert(1) cuckoo_insert(2) cuckoo_insert(4) cuckoo_insert(8) cuckoo_insert(16) cuckoo_insert(32) cuckoo_insert(64) cuckoo_insert(128) cuckoo_insert(256) cuckoo_insert(512) cuckoo_insert(1024) cuckoo_insert(2048) cuckoo_insert(4096) cuckoo_insert(8192) cuckoo_insert(16384) cuckoo_insert(32768) cuckoo_insert(65536) key T1 T2 === === === 0 65536 1 256 1 2 16384 8192 3 32 4 32768 4 5 128 2048 6 7 64 16 8 512 key T3 === === 0 4096 1 1024 2 8 3 2 7 entries cached on T1[] , 6 entries cached on T2[] and 4 entries in T3[] 17 / 17 = 100% insertions OK :) load factor = 13 / 18 = 72% extension factor = 4 / 18 = 22% extended
=> J'aimerais bien augmenter le nombre de fonctions de hachages utilisables par le banc de filtres, en l'étendant à 3 ou 4 quatres fonctions de hachage distinctes plutôt que les "seulement** 2 fonctions h1() et h2() actuellement utilisées
==> faut-il bien que je regarde du côté des filtres de Bloom ???
Partager