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.
- 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).
- 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.
- 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).
- 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.
- 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)
? Sihash
est "assez bon", alors que c'est "assez bon", n'est-ce pas? En supposant quehash(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!
Vous devez vous connecter pour publier un commentaire.
Prendre un coup d'oeil à la 128-bit de MurmurHash3. Le l'algorithme de la page comprend certains chiffres de la performance. Devrait être possible de porter ce Python, pure ou comme une extension de do. (Mis à jour l'auteur recommande d'utiliser le 128-bit et d'en jeter les morceaux que vous n'avez pas besoin).
Si MurmurHash2 64 bits qui fonctionne pour vous, il est un Python de mise en œuvre (C extension) dans le pyfasthash paquet, qui comprend quelques autres non-hachage cryptographique variantes, si certains d'entre eux offrent seulement 32 bits de sortie.
Mise à jour j'ai fait une rapide wrapper Python pour le Murmur3 fonction de hachage. Projet Github est ici et vous pouvez le trouver sur Python Package Index; il a juste besoin d'un compilateur C++ pour construire; pas de Boost nécessaire.
Exemple d'utilisation et le calendrier de comparaison:
De sortie:
sudo apt-get install libboost-python-dev
. J'ai construit un package dans mon PPA comme un exemple.Ce n'est pas vrai. Le construit en fonction de hachage va générer une version 64 bits de hachage sur un système 64 bits.
C'est le python str fonction de hachage à partir de
Objects/stringobject.c
(version de Python 2.7):hash()
fonction de hachage de la randomisation dans Python 3.3. Si la floraison filtre doit être en mesure d'être écrites sur le disque, puis le haut-hash()
fonction ne peut pas être utilisé.hash()
sur différentes instances il est donc inutile de tout ce qui doit être partagée entre deux ou plusieurs "machines" (dynamomètres dans le cas de heroku)"strings": je suis en supposant que vous souhaitez hachage Python 2.x
str
objets et/ou Python3.xbytes
et/oubytearray
objets.Cela pourrait violer votre première contrainte, mais: pensez à utiliser quelque chose comme
pour obtenir une (32+N) bits de hachage.
str
objets - je vais regarder dans cet extrait de code, merci, mais vous avez raison, je doute personnellement qu'il est cohérent d'entropie pour chaque bit de sortie ici. Merci bien!Si vous pouvez utiliser Python 3.2, le résultat du hachage sur Windows 64 bits est maintenant une valeur de 64 bits.