Como usar o GNU paralelamente de forma eficaz

7

Suponha que eu queira encontrar todas as correspondências no arquivo de texto compactado:

$ gzcat file.txt.gz | pv --rate -i 5 | grep some-pattern

pv --rate usado aqui para medir o throughput do tubo. Na minha máquina é cerca de 420Mb / s (após a descompressão).

Agora estou tentando fazer grep paralelo usando o GNU paralelo.

$ gzcat documents.json.gz | pv --rate -i 5 | parallel --pipe -j4 --round-robin grep some-pattern

Agora, o rendimento é reduzido para ~ 260Mb / s. E o que é mais intresting parallel processo em si está usando um monte de CPU. Mais de grep processa (mas menos que gzcat ).

EDIT 1 : tentei diferentes tamanhos de bloco ( --block ), além de valores diferentes para as opções -N / -L . Nada me ajuda neste momento.

O que estou fazendo de errado?

    
por Denis Bazhenov 03.02.2015 / 11:05

3 respostas

7

Eu estou realmente surpreso que você tenha 270 MB / s usando --pipe do GNU Parallel. Meus testes geralmente estão em torno de 100 MB / s.

Seu gargalo é mais provável no Paralelo GNU: --pipe não é muito eficiente. --pipepart , no entanto, é: Aqui eu posso obter na ordem de 1 GB / s por núcleo da CPU.

Infelizmente, existem algumas limitações no uso de --pipepart :

  • O arquivo deve ser pesquisável (ou seja, sem pipe)
  • Você deve conseguir encontrar o início de um registro com --recstart / - recend (ou seja, nenhum arquivo compactado)
  • O número da linha é desconhecido (portanto, você não pode ter um registro de 4 linhas).

Exemplo:

parallel --pipepart -a bigfile --block 100M grep somepattern
    
por 03.02.2015 / 14:40
2

o grep é muito eficaz - não faz sentido executá-lo em paralelo. No seu comando, apenas a descompressão precisa de mais cpu, mas isso não pode ser feito em paralelo.

A divisão da entrada pelo paralelo precisa de mais cpu do que a obtenção de linhas correspondentes pelo grep.

Mudança de situação se você quiser usar no lugar do grep algo que precisa de muito mais cpu para cada linha - então o paralelo teria mais sentido.

Se você deseja agilizar esta operação - veja onde estão gargalos - provavelmente é descompressão (ajuda a usar outra ferramenta de descompactação ou melhor cpu) ou - leitura de disco (então ajude a usar outra ferramenta de descompressão ou melhor sistema de disco). p>

Da minha experiência - às vezes é melhor usar o lzma (-2 por exemplo) para compactar / descompactar arquivos - ele tem uma compactação maior do que o gzip e muito menos dados precisam ser lidos do disco e a velocidade é comparável.

    
por 03.02.2015 / 11:40
1

A descompressão é o gargalo aqui. Se a descompressão não for paralelizada internamente, você não conseguirá isso sozinho. Se você tiver mais de um trabalho como esse, então, é claro, inicie-os em paralelo, mas seu pipeline por si só é difícil de paralelizar. Dividir um fluxo em fluxos paralelos quase nunca vale a pena, e pode ser muito doloroso com sincronização e mesclagem. Às vezes você só precisa aceitar que vários núcleos não ajudarão em todas as tarefas que você está executando.

Em geral, a paralelização em shell deve estar principalmente no nível de processos independentes.

    
por 03.02.2015 / 11:46