Come avviare grep multi-thread nel terminale?


38

Ho una cartella che contiene oltre 250 file da 2 GB ciascuno. Ho bisogno di cercare una stringa / modello in quei file e produrre il risultato in un outputfile. So di poter eseguire il seguente comando, ma è troppo lento !!

grep mypattern * > output

Voglio accelerarlo. Essendo un programmatore in Java, so che il multi-threading può essere utilizzato per accelerare il processo. Sono bloccato su come iniziare grepin "modalità multi-thread" e scrivere l'output in un singolo outputfile.




1
Sicuramente la ricerca di una grande raccolta di file è il classico esempio di un problema legato all'IO. Quindi l'utilizzo di più thread non sarà di aiuto.
Jonathan Hartley,

Risposte:


31

Ci sono due soluzioni facili per questo. Fondamentalmente, usando xargso parallel.

Approccio xargs:

È possibile utilizzare xargscon findil seguente:

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

Dove sostituirai number_of_processescon il numero massimo di processi che desideri avviare. Tuttavia, ciò non è garantito per offrire prestazioni significative nel caso in cui le prestazioni siano limitate in termini di I / O. Nel qual caso potresti provare ad avviare più processi per compensare il tempo perso in attesa di I / O.

Inoltre, con l'inclusione di find, è possibile specificare opzioni più avanzate anziché solo modelli di file, come il tempo di modifica, ecc ...

Un possibile problema con questo approccio, come spiegato dai commenti di Stéphane, se ci sono pochi file, xargspotrebbe non avviare abbastanza processi per loro. Una soluzione sarà quella di utilizzare l' -nopzione per xargsspecificare quanti argomenti dovrebbero prendere dalla pipe alla volta. L'impostazione -n1forzerà xargsl'avvio di un nuovo processo per ogni singolo file. Questo potrebbe essere un comportamento desiderato se i file sono molto grandi (come nel caso di questa domanda) e c'è un numero relativamente piccolo di file. Tuttavia, se i file stessi sono piccoli, il sovraccarico di iniziare un nuovo processo potrebbe minare il vantaggio del parallelismo, nel qual caso un -nvalore maggiore sarà migliore. Pertanto, l' -nopzione potrebbe essere ottimizzata in base alle dimensioni e al numero del file.

Approccio parallelo:

Un altro modo per farlo è utilizzare lo strumento Parallelo Ole Tange GNU parallel(disponibile qui ). Ciò offre un maggiore controllo del parallelismo e può anche essere distribuito su più host (sarebbe utile se la tua directory fosse condivisa, ad esempio). La sintassi più semplice usando il parallelo sarà:

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

dove l'opzione -j+1indica al parallelo di avviare un processo in eccesso rispetto al numero di core sulla macchina (questo può essere utile per le attività limitate di I / O, si può anche provare ad aumentare il numero).

Parallelamente ha anche il vantaggio xargsdi conservare effettivamente l'ordine dell'output di ciascun processo e generare un output contiguo. Ad esempio, xargsse, se il processo 1 genera una riga p1L1, il processo 2 genera una riga p2L1, il processo 1 genera un'altra riga p1L2, l'output sarà:

p1L1
p2L1
p1L2

mentre con parallell'output dovrebbe essere:

p1L1
p1L2
p2L1

Questo di solito è più utile xargsdell'output.


1
Probabilmente vorresti usarlo -nin combinazione con -P. Altrimenti, xargspotrebbe non finire la generazione di più processi se ci sono due pochi file.
Stéphane Chazelas,

1
Bene, -n1 ne avvierebbe uno grepper file. A meno che i file non siano molto grandi e ce ne siano pochi, probabilmente vorrai aumentarlo un po 'mentre passerai il tuo tempo a iniziare e interrompere i processi grep invece di cercare nei file.
Stéphane Chazelas,

9

Esistono almeno due modi per velocizzare la CPU di grep:

  • Se stai cercando una stringa fissa anziché un'espressione regolare, specifica il -Fflag;

  • Se il modello è solo ASCII, utilizzare una locale a 8 bit anziché UTF-8, ad es LC_ALL=C grep ....

Questi non aiuteranno però se il tuo disco rigido è il collo di bottiglia; in quel caso probabilmente anche il parallelismo non sarà di aiuto.


1
Ho appena visto man grep"L'invocazione diretta come egrep o fgrep è obsoleta, ma viene fornita per consentire l'esecuzione di applicazioni non modificate su applicazioni storiche che fanno affidamento su di esse". Non sono sicuro che questo abbia davvero importanza, ma è lo stesso digrep -F
iyrin

1
Anche quando dici "piuttosto che uno schema" ti riferisci a un'espressione regolare?
iyrin,

La ricerca "Solo ASCII" utilizza una CPU notevolmente inferiore. Ma è necessario leggere le avvertenze indicate nei commenti a stackoverflow.com/a/11777835/198219
famzah

3

Se il problema non è associato all'I / O, è possibile utilizzare uno strumento ottimizzato per l'elaborazione multi-core.

Potresti dare un'occhiata a setaccio ( http://sift-tool.org , disclaimer: sono l'autore di questo strumento) o il cercatore d'argento ( https://github.com/ggreer/the_silver_searcher ).

il cercatore d'argento ha un limite di dimensione del file di 2 GB se si utilizza un modello regex e non una ricerca di stringa spimple.


Sicuramente la ricerca di un mucchio di file è un classico esempio di problema legato all'IO?
Jonathan Hartley,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.