Comment démarrer grep multi-threaded en terminal?


38

J'ai un dossier qui a plus de 250 fichiers de 2 Go chacun. Je dois rechercher une chaîne / un motif dans ces fichiers et afficher le résultat dans un outputfichier. Je sais que je peux exécuter la commande suivante, mais elle est trop lente !!

grep mypattern * > output

Je veux accélérer les choses. En tant que 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 grepen "mode multi-thread" et d'écrire la sortie dans un seul outputfichier.




1
La recherche dans une vaste collection de fichiers est l'exemple classique d'un problème lié à l'IO. Par conséquent, utiliser plusieurs threads ne vous aidera pas.
Jonathan Hartley

Réponses:


31

Il existe deux solutions faciles pour cela. Fondamentalement, en utilisant xargsou parallel.

Approche de xargs:

Vous pouvez utiliser xargsavec findcomme suit:

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

Où vous allez remplacer number_of_processespar le nombre maximal de processus que vous souhaitez lancer. Toutefois, cela ne garantit pas une performance significative au cas où vos performances seraient limitées en entrées / sorties. Dans ce cas, vous pouvez essayer de démarrer plusieurs processus pour compenser le temps perdu à attendre des E / S.

En outre, avec l’inclusion de find, vous pouvez spécifier des options plus avancées au lieu de simplement des modèles de fichiers, tels que la date de modification, etc.

Un problème possible avec cette approche, comme l'expliquent les commentaires de Stéphane, xargspeut ne pas démarrer suffisamment de processus s'il y a peu de fichiers . Une solution consiste à utiliser l' -noption pour xargsspécifier le nombre d'arguments à prendre à la fois dans le canal. Le réglage -n1obligera xargsà démarrer un nouveau processus pour chaque fichier. Ce comportement peut être souhaité si les fichiers sont très volumineux (comme dans le cas de cette question) et si le nombre de fichiers est relativement petit. Toutefois, si les fichiers eux-mêmes sont petits, les frais généraux liés au démarrage d’un nouveau processus risquent de compromettre l’avantage du parallélisme, auquel cas une -nvaleur plus grande sera meilleure. Ainsi, l' -noption peut être ajustée en fonction de la taille et du nombre de fichiers.

Approche parallèle:

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

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

lorsque l'option -j+1indique en parallèle de démarrer un processus au-delà 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).

Parallèle a également l'avantage xargsde 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 p1L1, le processus 2 génère une ligne p2L1, le processus 1 génère une autre ligne p1L2, le résultat sera:

p1L1
p2L1
p1L2

alors qu'avec parallella sortie devrait être:

p1L1
p1L2
p2L1

Ceci est généralement plus utile que la xargssortie.


1
Vous voudrez probablement utiliser -nen combinaison avec -P. Sinon, il est xargspossible que plusieurs processus ne soient pas générés s'il y a deux fichiers.
Stéphane Chazelas

1
Eh bien, -n1 en commencerait un greppar fichier. À moins que les fichiers ne soient très volumineux et qu’ils soient très peu nombreux, vous voudrez probablement l’augmenter un peu car vous passerez votre temps à démarrer et à arrêter des processus grep au lieu de chercher dans des fichiers.
Stéphane Chazelas

9

Il y a au moins deux façons d'accélérer le traitement de grep par le processeur:

  • Si vous recherchez une chaîne fixe plutôt qu'une expression régulière, spécifiez l' -Findicateur.

  • 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 ne vous aidera probablement pas non plus.


1
Je viens de voir dans man grep"L'invocation directe comme étant egrep ou fgrep est obsolète, mais est fournie pour permettre aux applications historiques qui en dépendent de s'exécuter sans modification". Je ne suis pas sûr que cela compte vraiment, mais c'est la même chose quegrep -F
iyrin

1
De même, lorsque vous dites "plutôt qu'un motif", faites-vous référence à une expression régulière?
iyrin

La recherche "ASCII uniquement" utilise énormément moins de ressources processeur. Mais vous devez lire les réserves mentionnées dans les commentaires à stackoverflow.com/a/11777835/198219
Famzah

3

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 oeil à tamiser ( http://sift-tool.org , disclaimer: je suis l'auteur de cet outil) ou le chercheur d'argent ( https://github.com/ggreer/the_silver_searcher ).

Silver Searcher a une limite de taille de fichier de 2 Go si vous utilisez un motif regex et non une recherche par chaîne.


La recherche dans un groupe de fichiers est certainement un exemple classique d’un problème lié aux entrées-sorties.
Jonathan Hartley
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.