web-dev-qa-db-fra.com

Comment démarrer grep multi-thread dans le terminal?

J'ai un dossier qui contient plus de 250 fichiers de 2 Go chacun. J'ai besoin de rechercher une chaîne/un motif dans ces fichiers et de produire le résultat dans un fichier output. Je sais que je peux exécuter la commande suivante, mais c'est trop lent !!

grep mypattern * > output

Je veux accélérer. Étant programmeur en Java, je sais que le multi-threading peut être utilisé pour accélérer le processus. Je suis coincé sur la façon de démarrer grep en "mode multi-thread" et d'écrire la sortie dans un seul fichier output.

40
Abhishek

Il existe deux solutions simples pour cela. Fondamentalement, en utilisant xargs ou parallel.

Approche xargs:

Vous pouvez utiliser xargs avec find comme suit:

find . -type f -print0  | xargs -0 -P number_of_processes grep mypattern > output

Où vous remplacerez number_of_processes Par le nombre maximum de processus que vous souhaitez lancer. Cependant, cela n'est pas garanti pour vous donner des performances significatives au cas où vos performances seraient limitées en E/S. Dans ce cas, vous pouvez essayer de démarrer plus de processus pour compenser le temps perdu à attendre les E/S.

De plus, avec l'inclusion de find, vous pouvez spécifier des options plus avancées au lieu de simplement des modèles de fichiers, comme le temps de modification, etc.

Un problème possible avec cette approche, comme l'expliquent les commentaires de Stéphane, s'il y a peu de fichiers, xargs peut ne pas démarrer suffisamment de processus pour eux. Une solution consiste à utiliser l'option -n Pour xargs pour spécifier le nombre d'arguments à prendre à la fois dans le tube. La définition de -n1 Forcera xargs à démarrer un nouveau processus pour chaque fichier unique. Cela peut être un comportement souhaité si les fichiers sont très volumineux (comme dans le cas de cette question) et qu'il y a un nombre relativement petit de fichiers. Cependant, si les fichiers eux-mêmes sont petits, la surcharge de démarrage d'un nouveau processus peut miner l'avantage du parallélisme, auquel cas une plus grande valeur -n Sera meilleure. Ainsi, l'option -n Peut être affinée en fonction de la taille et du nombre de fichiers.

Approche parallèle:

Une autre façon de le faire est d'utiliser Ole Tange GNU Outil parallèle parallel, (disponible ici ). Cela offre un meilleur contrôle du grain fin sur le parallélisme et peut même être distribué sur plusieurs hôtes (serait bénéfique si votre répertoire est partagé par exemple). La syntaxe la plus simple en utilisant parallèle sera:

find . -type f | parallel -j+1 grep mypattern

où l'option -j+1 indique à parallèle de démarrer un processus en plus du nombre de cœurs sur votre machine (cela peut être utile pour les tâches limitées d'E/S, vous pouvez même essayer d'augmenter le nombre).

Parallel a également l'avantage sur xargs de conserver réellement l'ordre de la sortie de chaque processus et de générer une sortie contiguë. Par exemple, avec xargs, si le processus 1 génère une ligne, dites p1L1, Le processus 2 génère une ligne p2L1, Le processus 1 génère une autre ligne p1L2, Le la sortie sera:

p1L1
p2L1
p1L2

alors qu'avec parallel la sortie devrait être:

p1L1
p1L2
p2L1

Ceci est généralement plus utile que la sortie xargs.

32
Bichoy

Il existe au moins deux façons d'accélérer grep au niveau du processeur:

  • Si vous recherchez une chaîne fixe plutôt qu'une expression régulière, spécifiez le -F drapeau;

  • Si votre modèle est uniquement ASCII, utilisez une locale 8 bits au lieu de UTF-8, par exemple LC_ALL=C grep ....

Cela n'aidera pas si votre disque dur est le goulot d'étranglement; dans ce cas, la parallélisation n'aidera probablement pas non plus.

10
egmont

Si le problème n'est pas lié aux E/S, vous pouvez utiliser un outil optimisé pour le traitement multicœur.

Vous voudrez peut-être jeter un œil à sift ( http://sift-tool.org , avis de non-responsabilité: je suis l'auteur de cet outil) ou au chercheur d'argent ( https: // github.com/ggreer/the_silver_searcher ).

le chercheur argenté a une limite de taille de fichier de 2 Go si vous utilisez un modèle d'expression régulière et non une recherche de chaîne spimple.

3
svent