Como iniciar o multi-threaded grep no terminal?

33

Eu tenho uma pasta com mais de 250 arquivos de 2 GB cada. Eu preciso procurar por uma string / padrão nesses arquivos e gerar o resultado em um arquivo output . Eu sei que posso executar o seguinte comando, mas é muito lento!

grep mypattern * > output

Eu quero acelerar. Sendo um programador em Java, eu sei que o multi-threading pode ser usado para acelerar o processo. Estou preso em como iniciar grep no "modo multi-threaded" e escrever a saída em um único arquivo output .

    
por Abhishek 20.04.2015 / 06:38

3 respostas

27

Existem duas soluções fáceis para isso. Basicamente, usando xargs ou parallel .

xargs Approach:

Você pode usar xargs com find da seguinte forma:

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

Onde você substituirá number_of_processes pelo número máximo de processos que você deseja iniciar. No entanto, isso não garante um desempenho significativo, caso seu desempenho seja limitado a E / S. Nesse caso, você pode tentar iniciar mais processos para compensar o tempo perdido na espera por E / Ss.

Além disso, com a inclusão de find, você pode especificar opções mais avançadas em vez de apenas padrões de arquivo, como tempo de modificação, etc ...

Um problema possível com essa abordagem, conforme explicado pelos comentários de Stéphane, se houver poucos arquivos, xargs pode não iniciar processos suficientes para eles. Uma solução será usar a opção -n para xargs para especificar quantos argumentos devem ser obtidos do pipe por vez. A configuração -n1 forçará xargs a iniciar um novo processo para cada arquivo único. Este pode ser um comportamento desejado se os arquivos forem muito grandes (como no caso desta questão) e houver um número relativamente pequeno de arquivos. No entanto, se os próprios arquivos forem pequenos, a sobrecarga de iniciar um novo processo poderá prejudicar a vantagem do paralelismo, caso em que um maior valor -n será melhor. Assim, a opção -n pode ser ajustada de acordo com o tamanho e o número dos arquivos.

Abordagem Paralela:

Outra maneira de fazer isso é usar a ferramenta Paralela GNU Ole Tange, parallel , (disponível aqui ). Isso oferece maior controle de granularidade sobre paralelismo e pode até mesmo ser distribuído em vários hosts (seria benéfico se seu diretório fosse compartilhado, por exemplo).  A sintaxe mais simples usando o paralelo será:

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

em que a opção -j+1 é instruída em paralelo para iniciar um processo além do número de núcleos em sua máquina (isso pode ser útil para tarefas limitadas de E / S, você pode até tentar aumentar em número).

O paralelismo também tem a vantagem sobre xargs de realmente reter a ordem da saída de cada processo e gerar uma saída contígua. Por exemplo, com xargs , se o processo 1 gerar uma linha, digamos p1L1 , o processo 2 gera uma linha p2L1 , o processo 1 gera outra linha p1L2 , a saída será:

p1L1
p2L1
p1L2

Considerando que com parallel a saída deve ser:

p1L1
p1L2
p2L1

Isso geralmente é mais útil que xargs output.

    
por 20.04.2015 / 06:47
8

Existem pelo menos duas maneiras de acelerar o uso da CPU:

  • Se você estiver procurando por uma string fixa em vez de uma expressão regular, especifique o -F flag;

  • Se o seu padrão for somente ASCII, use um código de idioma de 8 bits em vez de UTF-8, por exemplo, LC_ALL=C grep ... .

Isso não ajudará se o seu disco rígido for o gargalo; Nesse caso, provavelmente a paralelização também não ajudará.

    
por 25.04.2015 / 19:59
3

Se o problema não for vinculado a E / S, você poderá usar uma ferramenta otimizada para processamento de vários núcleos.

Você pode querer dar uma olhada no sift ( link , disclaimer: eu sou o autor desta ferramenta) ou no pesquisador de prata ( link ).

o pesquisador prateado tem um limite de tamanho de arquivo de 2 GB se você usar um padrão de regex e não uma pesquisa de cadeia de espinha.

    
por 23.04.2015 / 00:27