rapide, de grande largeur, non cryptographique chaîne de hachage en python

J'ai un besoin pour une haute performance de la chaîne de fonction de hachage en python qui produit des entiers avec au moins 34 bits de sortie (64 bits serait logique, mais 32 est trop peu). Il y a plusieurs autres questions de ce genre sur un Débordement de Pile, mais de ceux de tous les acceptée/upvoted réponse que j'ai pu trouver est tombé dans l'une des catégories suivantes, qui ne s'appliquent pas (pour la raison.)

  • Utiliser le haut- hash() fonction. Cette fonction, au moins sur la machine que je suis en développement (avec python 2.7, et un processeur 64 bits) produit un nombre entier qui correspond à l'intérieur de 32 bits - pas assez grand pour mes fins.
  • Utilisation hashlib. hashlib offre de hachage cryptographique routines, qui sont loin plus lentement qu'ils doivent être pour les non-cryptographiques fins. Je trouve cette auto-évident, mais si vous avez besoin de repères et de citations pour vous convaincre de ce fait, alors je peux leur fournir.
  • Utiliser le string.__hash__() fonction comme un prototype pour écrire votre propre fonction. J'imagine que ce sera la bonne façon de procéder, sauf que cette fonction de l'efficacité réside dans son utilisation de la c_mul fonction, qui s'enroule autour de 32 bits - encore une fois, trop petit pour mon utilisation! Très frustrant, c'est tellement proche de la perfection!

Une solution idéale serait d'avoir les propriétés suivantes, dans une relative, sans ordre d'importance.

  1. Ont une gamme de puissance s'étend au moins 34 bits de long, probablement en 64 bits, tout en préservant cohérente avalanche propriétés de plus de tous bits. (Concaténation de 32 bits hachages tend à violer l'avalanche propriétés, au moins avec mon mutisme des exemples).
  2. Portable. Compte tenu de la même chaîne d'entrée sur deux machines différentes, je devrais obtenir le même résultat à chaque fois. Ces valeurs seront stockées dans un fichier pour une utilisation ultérieure.
  3. De haute performance. Le plus rapide est le mieux que cette fonction sera appelée à près de 20 milliards de fois au cours de l'exécution du programme que je suis en cours d'exécution (c'est la critique de code pour le moment.) Il n'a pas besoin d'être écrit en C, il est vraiment juste besoin de surpasser md5 (quelque part dans le royaume de l'intégré dans la table de hachage() pour les chaînes).
  4. Accepter une "perturbation" (quel est le meilleur terme à utiliser, ici?) entier comme entrée pour modifier la sortie. J'ai mis un exemple ci-dessous (la liste des règles de mise en forme ne m'a pas permis de le placer le plus proche.) Je suppose que ce n'est pas 100% nécessaire car il peut être simulé en perturbant la sortie de la fonction manuellement, mais l'avoir en entrée me donne une agréable sensation de chaleur.
  5. Entièrement écrit en Python. Si absolument, positivement besoins être écrit en C alors je suppose que peut être fait, mais je voudrais prendre un 20% plus lent fonction écrite en python sur le plus rapide en C, juste à cause de la coordination du projet de maux de tête à l'aide de deux langues différentes. Oui, c'est une dérobade, mais c'est une liste de souhaits ici.

"Perturbée" de hachage exemple, où la valeur de hachage est changé radicalement par une petite valeur entière n

def perturb_hash(key,n):
    return hash((key,n))

Enfin, si vous êtes curieux de savoir ce que le diable, je suis en train de faire que j'ai besoin d'un tel spécifique de la fonction de hachage, je suis en train de faire une réécriture complète de la pybloom module afin d'améliorer ses performances considérablement. J'ai réussi à l' (il se situe maintenant à environ 4x plus rapide et consomme environ 50% de l'espace), mais j'ai remarqué que, parfois, si le filtre a obtenu assez grand, il était soudain de dopage dans le taux de faux positifs. J'ai réalisé que c'était à cause de la fonction de hachage n'était pas aborder assez de bits. 32 bits ne s'adresse qu'à 4 milliards de bits (vous l'esprit, le filtre des adresses de bits et non d'octets) et certains filtres que j'utilise pour les données de la génomique du double ou plus (donc 34 bits minimum.)

Merci!

  • Il n'y a rien de mal avec hash(s) * 2**32 + hash(s+s)? Si hash est "assez bon", alors que c'est "assez bon", n'est-ce pas? En supposant que hash(s+s) porte pas discernable rapport à hash(s), puis vous obtenez votre avalanche dans tous les bits de sortie. Et si ce n'est pas assez rapide en raison de l'allocation de mémoire, vous pouvez coder en C pour effet d'appliquer l'algorithme de hachage à s+s, mais sans réellement effectuer la concaténation de chaîne.
  • Donc, en d'autres termes, hash(s)<<32 + hash(s+s). Je vais donner un coup de feu - merci pour l'idée!
InformationsquelleAutor eblume | 2011-03-23