Estou procurando implementar uma tabela de hash rápida e bem distribuída em C #. Estou tendo problemas para escolher minha função de restrição de hash que usa um código de hash arbitrário e a "restringe" para que possa ser usada para indexar os buckets. Existem duas opções que vejo até agora:
Por um lado, você pode garantir que seus depósitos sempre tenham um número primo de elementos e, para restringir o hash, basta modulá-lo pelo número de depósitos. Na verdade, é isso que o Dicionário do .NET faz . O problema com essa abordagem é que o uso de% é extremamente lento em comparação com outras operações; se você olhar para as tabelas de instruções do Agner Fog ,
idiv
(que é o código de montagem gerado para%), possui uma latência de instruções de ~ 25 ciclos para os processadores Intel mais novos. Compare isso com cerca de 3 pormul
, ou 1 para ops bit a bit comoand
,or
ouxor
.Por outro lado, você pode ter o número de buckets sempre com uma potência de 2. Você ainda precisará calcular o módulo do hash para não tentar indexar fora da matriz, mas desta vez será menos caro . Como as potências de 2
% N
são justas& (N - 1)
, a restrição é reduzida a uma operação de mascaramento que leva apenas 1-2 ciclos. Isso é feito pelo esparso do Google . A desvantagem disso é que estamos contando com os usuários para fornecer bons hashes; mascarar o hash corta essencialmente parte do hash, portanto, não estamos mais levando em consideração todos os bits do hash. Se o hash do usuário é distribuído de maneira desigual, por exemplo, apenas os bits mais altos são preenchidos ou os bits mais baixos são sempre os mesmos, então essa abordagem tem uma taxa muito maior de colisões.
Estou procurando um algoritmo que eu possa usar que tenha o melhor dos dois mundos: leva em consideração todos os bits do hash e também é mais rápido do que usar%. Ele não precisa necessariamente ser um módulo, apenas algo que está garantido no intervalo 0..N-1
(onde N é o comprimento dos baldes) e tem distribuição uniforme para todos os slots. Existe um algoritmo desse tipo?
Obrigado por ajudar.
(2^N +/- 1)
, consulte stackoverflow.com/questions/763137/…