Il y a une chaîne de 1 gigaoctet de données arbitraires que vous pouvez supposer d'être équivalente à quelque chose comme: Nous rechercherons cette chaîne, Notez que seule la première occurrence du motif doit être trouvée. Après cela, aucun autre traitement majeur ne devrait être fait. P> Que puis-je utiliser qui est plus rapide que la recherche de Python de la recherche pour assortir des modèles de 1kb sur 1 Go ou plus de chaînes de données? P> (je suis déjà Conscient de la façon de fragmenter la chaîne et de la rechercher en parallèle, vous pouvez donc ignorer cette optimisation de base.) p> mise à jour: Veuillez limiter les exigences de mémoire à 16 Go. P> P> 1_gb_string code>, car Un nombre infini de largeur fixe, 1 kilobyte motifs,
1_kb_pattern code>. Chaque fois que nous recherchons, le motif sera différent. Les opportunités de mise en cache ne sont donc pas apparentes. La même chaîne de gigaoctet sera recherchée. Voici un générateur simple pour décrire ce qui se passe: p>
10 Réponses :
avec une mémoire infinie, vous pouvez hacher chaque chaîne 1k avec sa position dans le fichier 1 Go. P>
Avec moins de mémoire infinie, vous serez délimité par le nombre de pages de mémoire que vous touchez lors de la recherche. P>
Il existe un certain nombre d'algorithmes correspondants à chaîne utilisent dans le domaine de la génétique pour trouver des sous-chaînes. Vous pouvez essayer Ce papier ou Ce papier P>
Ne voyez pas encore un ajustement parfait, mais quelque chose sur ces lignes peut être la voie à suivre. La mise en cache générique et la programmation dynamique Comme d'autres suggérons n'est pas pratique, car cela épuira rapidement toute la mémoire.
Êtes-vous prêt à passer un temps significatif prétraiter la chaîne?
Si vous êtes, ce que vous pouvez faire est de construire une liste de n-grammes avec des compensations. P>
Supposons que votre alphabet soit hextone et vous utilisez 1-grammes. P>
puis pour 00-ff, vous pouvez créer un dictionnaire qui ressemble à ceci (perlee, désolé) p> où vous marchez dans la chaîne et construire @array_of_offsets de tous les points où les octets se produisent. Vous pouvez le faire pour les N-grammes arbitraires. P> Ceci fournit un "point de départ pour la recherche" que vous pouvez utiliser pour marcher. p> Bien sûr, l'inconvénient est que vous devez prépraquer la chaîne, c'est donc votre compromis. P> EDIT: P> L'idée de base ici est correspondre aux préfixes. Cela peut bombarder mal si les informations sont super-mêmes, mais s'il a une juste quantité de divergence entre N-grammes, vous devriez être en mesure de faire correspondre assez bien les préfixes. P> Quantifier divergence, puisque vous Je n'ai pas discuté du type d'informations que vous analysez. Aux fins de cet algorithme, nous pouvons caractériser la divergence comme fonction de distance: vous avez besoin d'un décemment em> haut Pour améliorer mon algorithme, construisons un algorithme qui fait une élimination successive des possibilités: P> Nous pouvons invoquer Shannon Entropy pour définir des informations d'un N-gramme donné. Prenez votre chaîne de recherche et créez successivement un préfixe en fonction des premiers caractères. Lorsque l'entropie du préfixe M est suffisamment élevée, utilisez-la plus tard. P> dans un sens, c'est comme inversant le codage de Huffman. P> P>
Je suis prêt à dépenser un prétraitement de temps significatif, mais seulement jusqu'à 16 Go de mémoire aérienne pour cette chaîne de 1 Go.
Eh bien, cela signifie que vos ngrams doivent probablement être de l'ordre de 32 grammes (8 Go de mémoire stockant des ngams).
Je ne sais pas définitivement si la méthode Si vous recherchez une chaîne, ce que vous voulez, c'est ceci: p> () code> est plus rapide que la méthode de recherche
code> fourni par Python's
re code> (expressions régulières) module, mais il n'y a qu'un seul moyen de savoir.
import re
def findit(1_gb_string):
yield re.search(1_kb_pattern, 1_gb_string)
http://www.youtube.com/watch?v=v5HZOJ6UK-S Sera de la plus utile pour vous. C'est une conférence mit sur la programmation dynamique p>
Autant que je sache, Standard Trouver Algorithme est un algorithme naïf avec une complexité sur les comparaisons N * M, car Il vérifie les modèles contre chaque décalage possible. Il existe des algoithmes plus efficaces nécessitant des comparaisons N + M. Si votre chaîne n'est pas une chaîne de langue naturelle, vous pouvez essayer algorithme Knuth-Morris-Pratt . Boyer-Moore Rechercher Algorithme est assez rapide et assez simple. P>
Si les motifs sont assez aléatoires, vous pouvez précomputer l'emplacement des n-préfixes de chaînes.
au lieu de passer sur toutes les options pour N-préfixes, utilisez simplement les réelles dans la chaîne 1GB - il y aura moins que 1gig de ceux-ci. Utilisez comme gros préfixe comme convient à votre mémoire, je n'ai pas 16 Go de RAM pour vérifier, mais un préfixe de 4 pourrait fonctionner (au moins dans une structure de données efficace de la mémoire), sinon essayer 3 ou même 2. P >
Pour une chaîne aléatoire de 1 Go et des motifs de 1kb aléatoires, vous devez obtenir quelques emplacements 10 par préfixes si vous utilisez des préfixes de 3 octets, mais les préfixes de 4 octets devraient vous procurer une moyenne de 0 ou 1. Sois rapide. P>
Emplacements précalcompute strong> p> def find_pattern(pattern):
prefix = pattern[:PREFIX_SIZE]
# optimization - big prefixes will result in many misses
if prefix not in precomputed_indices:
return -1
for loc in precomputed_indices[prefix]:
if big_string[loc:loc+CHUNK_SIZE] == pattern:
return loc
return -1
Lorsque vous précisez que le prétraitement ISH de longue date est acceptable, je suggérerais une variante de Rabin- Karp : "Un algorithme de choix pour la recherche de modèles multiples", comme le dit Wikipedia.
Définir une fonction "Rolling Hash", c'est-à-dire une telle sorte que, lorsque vous connaissez le hachage pour Ainsi, calculez 1 g de RH Résultats lorsque vous roulerez le long de la chaîne de foin 1GB; Si vous venez de stocker ceux-ci, cela vous donnerait un tableau H de valeurs 1G 30 bits (4 Go) de mappage Index-in-Haystack-> RH Valeur. Mais vous souhaitez que la mappage inverse, utilisez plutôt un tableau A de 2 ** 30 entrées (entrées 1G) que pour chaque valeur RH vous donne tous les indices d'intérêt dans les foines de foin (indices au cours de la mesure de la valeur RH); Pour chaque entrée, vous stockez l'indice du premier indice de fointstack potentiellement intéressant dans un autre tableau B d'indices 1G dans la grille de foin, qui est condamné à conserver tous les indices dans de la botte de foin avec des valeurs HR identiques ("collisions" en hachage) adjacentes. H, A et B ont tous les deux des entrées 1G de 4 octets chacun, donc 12 Go total. P> Maintenant pour chaque aiguille 1K entrante, calculez son HR, appelez-le k et utilisez-le comme index dans A; A [K] vous donne le premier index B en B auquel cela vaut la peine de comparer. Donc, faire: p> avec un bon rh, vous devez avoir peu de collisions, le moment devrait donc s'exécuter très peu de fois jusqu'à ce qu'il soit renvoyé d'une manière ou d'une autre. Donc, chaque recherche d'aiguille devrait être vraiment très rapide. P> p> HayStack [ x: x + n] code>, calculant le hachage pour
haunstack [x + 1: x + n + 1] code> est O (1). (Fonctions de hachage normales telles que l'intégrée intégrée de Python code> code> ne possède pas cette propriété, c'est pourquoi vous devez écrire votre propre, sinon le prétraitement devient épuréement em> long plutôt que simplement assez long;-). Une approche polynomiale est fructueuse et vous pourriez utiliser, disons des résultats de hachage 30 bits (en masquant si nécessaire, vous pouvez faire le calcul avec plus de précision et stockez simplement les 30 bits de choix masqués). Appelons cette fonction de hachage roulante RH pour la clarté. P>
Quelqu'un a laissé entendre une éventuelle moyen d'indexer cette chose si vous avez une valise abondante (ou éventuellement un disque / échange) disponible. P>
Imaginez si vous effectuez un simple CRC 32 bits sur un bloc de 1k s'étendant de chaque caractère de la chaîne de gig d'origine. Cela aboutirait à 4Bans de données de somme de contrôle pour chaque décalage d'octets dès le début des données. P>
Par lui-même, cela pourrait donner une amélioration modeste de la vitesse de recherche. La somme de contrôle de chaque cible de recherche 1k pourrait être vérifiée contre chaque CRC ... que chaque collision testée pour une correspondance véritable. Cela devrait toujours être un couple d'ordres de magnitude plus rapidement qu'une recherche linéaire normale. P>
Ce qui, évidemment, nous coûte 4 Go de RAM pour son tableau CRC (plus le concert d'origine pour les données d'origine et un peu plus de frais généraux pour l'environnement et notre programme). P>
Si nous avons ~ 16 Go, nous pourrions trier les checksums et stocker une liste de compensations où se trouve chacun. Cela devient une recherche indexée (moyenne d'environ 16 sondes par la recherche cibles ... Les pires cas d'environ 32 ou 33 (pourraient être un poste de clôture là-bas). P>
Il est possible qu'un index de fichier 16BG donnerait encore une meilleure performance qu'une recherche de contrôle linéaire et cela serait presque certainement mieux qu'une recherche brute linéaire (sauf si vous avez des systèmes de fichiers / stockages extrêmement lents). P>
(Ajout): Je devrais préciser que cette stratégie n'est bénéfique que pour que vous ayez décrit une nécessité de nombreuses recherches sur la même blob de données Gigabyte. P>
Vous pouvez utiliser une approche filetée pour construire l'index (tout en le lisant ainsi que plusieurs threads exécutant la checkingumming). Vous pouvez également décharger l'indexation dans des processus distincts ou un groupe de nœuds (en particulier si vous utilisez un index basé sur un fichier --- L'option ~ 16 Go décrit ci-dessus). Avec un simple CRC 32 bits, vous pourrez peut-être effectuer les checks / indexation aussi vite que votre filetage de votre lecteur peut obtenir les données (mais nous parlons de 1024 checksums pour chaque 1k de données, donc peut-être pas). P>
Vous pourriez améliorer encore les performances en codant un module Python en C pour effectuer réellement la recherche ... et / ou éventuellement pour effectuer la checkinguming / indexation. P>
Le développement et les tests de telles extensions C impliquent d'autres compromis, évidemment suffisamment. On dirait que cela aurait presque zéro réutilisabilité. P>
Une manière efficace mais complexe est Indexation du texte intégral avec la transformation BURROWS-Wheeler . Il s'agit d'effectuer un BWT sur votre texte source, puis d'utiliser un petit index sur lequel vous trouverez rapidement toute sous-chaîne dans le texte correspondant à votre modèle d'entrée. P>
La complexité temporelle de cet algorithme est grossièrement O (n) avec la longueur de la chaîne correspondante - et indépendante de la longueur de la chaîne d'entrée! En outre, la taille de l'indice n'est pas beaucoup plus grande que les données d'entrée et la compression peut même être réduite en dessous de la taille du texte source. P>
Est 1_gb_string susceptible de changer?
Cela ne sonne pas comme ça, mais ne cherchez-vous que sur les morceaux de largeur fixe? Comme dans, si c'était des octets et des mégaoctets au lieu de kilo-octets et de gigaoctets, une chaîne contenant les deux octets suivants: "49fa 32d1" correspondre au modèle de 1 octet de "FA32"?
> Est 1_gb_string susceptible de changer? Non, reste la même chose à travers toutes les pistes. > Ne cherchez-vous que sur les morceaux de largeur fixe? Malheureusement non.