Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1154 connectés 

  FORUM HardWare.fr
  Programmation
  Shell/Batch

  [script shell] grep -f sur de grandes quanités de données

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[script shell] grep -f sur de grandes quanités de données

n°1450647
nandao
Posté le 02-10-2006 à 10:22:49  profilanswer
 

Bonjour,  
 
je dois faire une recherche de la façon suivante  
:  
 
un fichier A contient 120 000 valeurs a tester qui  
sont des numéros.  
Un fichier B contient 10 000 000 de lignes qui  
commencent par des numéros qui sont  
potentiellement dans le fichier A  
 
Ce que je fais aujourd'hui :  
 
grep -f A B > resultats.  
 
Le temps de traitement est excessivement long (5  
jours) et je cherche à développer un programme  
qui me permette de résoudre le problème le plus  
rapidement possible (4 heures maximum).  
 
J'ai déjà effectué un tri sur les fichiers et mis, das mon fichier de valeur a tester, le critère ^(commence par).
 
Je me demandais s'il n'existait pas d'algorithme procedant par division de fichiers en sous fichiers et en parallelisant la recherche  
A=A1 +A2+...Ak  
 
B=B1+B2+....BN  
 
 
 
 
Une idée?  
 
Merci

mood
Publicité
Posté le 02-10-2006 à 10:22:49  profilanswer
 

n°1450659
0x90
Posté le 02-10-2006 à 10:46:36  profilanswer
 

J'ai pas de gros sets de donnée, mais essaye ca :

Code :
  1. #!/usr/bin/env python
  2. import bisect
  3.  
  4. mask = []
  5.  
  6. for line in file('A'):
  7.     bisect.insort(mask, int(line))
  8.  
  9. for line in file('B'):
  10.     key = int(line.split(' ', 1)[0])
  11.     if mask[bisect.bisect_left(mask, key)] == key:
  12.         print line,


python est pas franchement rapide, mais l'algo utilisé trie les valeur dans le fichier A puis utilise une dichotomie donc ca sera ptêtre plus rapide.
 
Sinon l'idée est reproductible en C, et la ce sera plus surement plus rapide que grep.


Message édité par 0x90 le 02-10-2006 à 10:47:04
n°1450762
Sve@r
Posté le 02-10-2006 à 13:53:26  profilanswer
 

nandao a écrit :

Bonjour,  
 
je dois faire une recherche de la façon suivante  
:  
 
un fichier A contient 120 000 valeurs a tester qui  
sont des numéros.  
Un fichier B contient 10 000 000 de lignes qui  
commencent par des numéros qui sont  
potentiellement dans le fichier A  
 
Ce que je fais aujourd'hui :  
 
grep -f A B > resultats.  
 
Le temps de traitement est excessivement long (5  
jours) et je cherche à développer un programme  
qui me permette de résoudre le problème le plus  
rapidement possible (4 heures maximum).  
 
J'ai déjà effectué un tri sur les fichiers et mis, das mon fichier de valeur a tester, le critère ^(commence par).
 
Je me demandais s'il n'existait pas d'algorithme procedant par division de fichiers en sous fichiers et en parallelisant la recherche  
A=A1 +A2+...Ak  
 
B=B1+B2+....BN  
 
 
 
 
Une idée?  
 
Merci


Va voir chez lea-linux si j'y suis [:ddr555]


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
n°1450972
aigles
Posté le 02-10-2006 à 18:05:56  profilanswer
 

Voici un petit script awk effectue le travail.
Il est dans le même esprit que le programme python que propose 0x90.
 
Il présuppose que le numéro dans le fichier B est suivi d'un espace (ou d'une tabulation).

awk 'NR==FNR { Num[$0] ; next } ($1 in Num)' A B


Si le séparateur dans le fichier B est autre chose qu'un blanc :

awk -v FS='separateur' 'NR==FNR { Num[$0] ; next } ($1 in Num)' A B


Autre cas, si le numéro est de longueur fixe et qu'il n'y a pas de séparateur dans B :

awk 'NR==FNR { Num[$0] ; next } (substr($0,1,longueur_numero)  in Num)' A B


 
Je n'ai aucune idée du temps que cela va prendre !
 
Jean-Pierre.


---------------
Jean Pierre.
n°1450975
0x90
Posté le 02-10-2006 à 18:09:53  profilanswer
 

Euh, je connais pas awk, mais t'es sur d'utiliser un algo dichotomique la ?

n°1451079
matafan
Posté le 02-10-2006 à 21:20:31  profilanswer
 

Tu ne veux garder que les lignes du fichier B qui commencent par un numero qui est dans le fichier A, c'est ca ? A ta place je ferais ca en Perl (ou Python, ou Ruby, ou tout autre langage de script). Dans un premier temps tu lis le fichier A ligne par ligne, et tu met toutes les valeurs dans un hash (les valeurs que tu lis sont les clees du hash). Puis tu lis le fichier B ligne par ligne, et a chaque fois tu regardes si le premier champs est dans le hash. Le hash c'est a mon avis la solution la plus rapide (et aussi la plus rapide a coder). Beaucoup plus rapide en tout ca qu'une recherche "a la main" par dichotomie.

n°1451082
Elmoricq
Modérateur
Posté le 02-10-2006 à 21:23:59  profilanswer
 

Je suis d'accord, c'est un cas où le shell, puissant et très pratique par ailleurs, montre ici ses limites : il n'est pas fait pour traiter de telles quantités de données (5j  :ouch: ).
 
PERL me semble être une bonne solution, surtout qu'il y a de bonne chance qu'il soit déjà installé. La solution de matafan me semble bien.
Celle de 0x90 en Python semble chouette aussi.


Message édité par Elmoricq le 02-10-2006 à 21:27:48
n°1451810
0x90
Posté le 03-10-2006 à 22:04:53  profilanswer
 

matafan a écrit :

Tu ne veux garder que les lignes du fichier B qui commencent par un numero qui est dans le fichier A, c'est ca ? A ta place je ferais ca en Perl (ou Python, ou Ruby, ou tout autre langage de script). Dans un premier temps tu lis le fichier A ligne par ligne, et tu met toutes les valeurs dans un hash (les valeurs que tu lis sont les clees du hash). Puis tu lis le fichier B ligne par ligne, et a chaque fois tu regardes si le premier champs est dans le hash. Le hash c'est a mon avis la solution la plus rapide (et aussi la plus rapide a coder). Beaucoup plus rapide en tout ca qu'une recherche "a la main" par dichotomie.


 
avec 120 000 valeurs dans un seul hash, j'ai eu peur de me retrouver avec des buckets extrachargés et donc de ramer pour rechercher dedans. ( j'ai eu la flemme de vérifier si python 1) resize les hash 2) trie les buckets, s'il le fait efficacement, alors ca peut être mieux avec un hash ).
 
Sinon y'a toujours des solutions sympa en C en générant un ptit automate en lisant le fichier A....

n°1451848
matafan
Posté le 04-10-2006 à 00:01:31  profilanswer
 

Perl n'a aucun probleme a gerer efficacement des hashs de plusieurs centaines de miliers de clees. C'est fait pour ca. D'ailleurs j'ai fait un petit test. Je genere un fichier a.txt qui contient 120,000 valeurs aleatoire entre 0 et 1,000,000,000, et un fichier b qui contient 10,000,000 lignes commencant par une valeur aleatoire egalement entre 0 et 1,000,000,000 :
 

nicolas@austin ~/tmp $ perl -e 'foreach (1 .. 120000) { print int(rand(1000000000)) . "\n" }' > a.txt
nicolas@austin ~/tmp $ perl -e 'foreach (1 .. 10000000) { print int(rand(1000000000)) . " blah blah blah\n" }' > b.txt


 
Puis je fait tourner ce petit script, qui fait ce que nandao demande :
 

nicolas@austin ~/tmp $ cat filter.pl  
#!/usr/bin/perl -w
 
use strict;
 
my %a;
 
open(A, $ARGV[0]) or die $!;
while (<A> ) {
        chomp;
        $a{$_} = 1;
}
close(A);
 
open(B, $ARGV[1]) or die $!;
while (<B> ) {
        my @tok = split(/\s+/);
        next if @tok == 0;
        chomp($tok[0]);
        print if $a{$tok[0]};
}
close(B);


 
Les resultats :
 

nicolas@austin ~/tmp $ time ./filter.pl a.txt b.txt > out
 
real    1m3.184s
user    1m1.247s
sys     0m0.332s


 
1 minute... Legerement plus rapide que les 5 jours de nandao  ;)

Message cité 1 fois
Message édité par matafan le 04-10-2006 à 20:35:33
n°1451890
Sve@r
Posté le 04-10-2006 à 08:56:57  profilanswer
 

matafan a écrit :

Perl n'a aucun probleme a gerer efficacement des hashs de plusieurs centaines de miliers de clees. C'est fait pour ca. D'ailleurs j'ai fait un petit test.1 minute... Legerement plus rapide que les 5 jours de nandao  ;)


 
Joli !!!
Est-ce que Python ferait aussi bien ???


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
mood
Publicité
Posté le 04-10-2006 à 08:56:57  profilanswer
 

n°1451963
Taz
bisounours-codeur
Posté le 04-10-2006 à 10:47:07  profilanswer
 

LC_ALL=C grep -f A B > resultats
 
ça fait souvent des étincelles.

n°1452139
0x90
Posté le 04-10-2006 à 14:52:55  profilanswer
 

J'ai testé avec la même quantité de donné (après avoir corrigé un ptit bug [:cupra] ) :
real    1m10.963s
user    1m5.109s
sys     0m0.981s
Je le refais en plus simple (en faisant confiance à la hashtable :D) :
real    0m28.883s
user    0m28.203s
sys     0m0.324s
 
Moralité, Je suis une grosse loutre :D
 
[edit] Simplification encore :
real    0m15.995s
user    0m15.835s
sys     0m0.155s


Message édité par 0x90 le 04-10-2006 à 15:02:25
n°1452262
aigles
Posté le 04-10-2006 à 16:15:16  profilanswer
 

J'ai testé les 3 méthodes awk, perl et grep sur mon système AIX avec le même volume de données (je ne dispose pas de python).
Voici les résultats :

awk  
real  1m14,81s  
user  1m7,86s
sys   0m2,27s
 
perl
real  3m17,72s
user  3m13,52s
sys   0m2,10s
 
grep
out of memory


A priori mon serveur semble à la traine par rapport aux votres (durée perl trois fois plus importante).
Ma commande grep s'est plantée au bout de deux secondes avec le message 'out of memory'
Pouvez vous tester avec awk et m'indiquer les temps obtenus.
 
Jean-Pierre.


---------------
Jean Pierre.
n°1452302
Elmoricq
Modérateur
Posté le 04-10-2006 à 16:53:44  profilanswer
 

Quoiqu'il en soit je ne vois pas comment obtenir les 5j de traitement, même awk est plus rapide, c'est pourtant pas un foudre de guerre [:pingouino]

n°1453646
Sve@r
Posté le 06-10-2006 à 21:56:47  profilanswer
 

Elmoricq a écrit :

Quoiqu'il en soit je ne vois pas comment obtenir les 5j de traitement[:pingouino]


Ptet que les lignes du fichier "B" sont très longues... :??:  


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
n°1453890
aigles
Posté le 07-10-2006 à 21:26:00  profilanswer
 

0x90 a écrit :

Euh, je connais pas awk, mais t'es sur d'utiliser un algo dichotomique la ?


En effet il ne s'agit pas d'un algo dichotomique.
Ceci étant, la structure des tableaux en awk est telle que cela revient au même à mes yeux.  
Les tableaux sont gérés sous forme d'arbre èquilibré, toutes les feuilles sont à la même profondeur dans l'arbre (à un niveau prés) et donc accessibles avec un nombre équivalent d'opérations.  
Une autre incidence de cette structure est que l'ordre des indices récupéré par uneboucle for in est imprédictible.
 
 


---------------
Jean Pierre.

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Shell/Batch

  [script shell] grep -f sur de grandes quanités de données

 

Sujets relatifs
help correction scriptun script pour automatiser l'impression de .pdf ?
Stockage de donnéesrecherche de données dans excel sans ouvrir les fichiers
Interdire l'accès a un dossier sauf a un scriptAJAX, renvoi de données
[PHP] adapter un script en une fonctionScript FTP automatisé
script pour avoir son navigateur en plein pageConseil sur une stratégie de base de données
Plus de sujets relatifs à : [script shell] grep -f sur de grandes quanités de données


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR