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 a produtividade do tubo. Na minha máquina, são cerca de 420 Mb / 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, a taxa de transferência caiu para ~ 260Mb / s. E o que é o parallel
processo mais interessante em si é usar muita CPU. Mais que grep
processos (mas menos que gzcat
).
Edição 1 : Eu tentei diferentes tamanhos de bloco ( --block
), bem como diferentes valores para -N
/ -L
options. Nada me ajuda neste momento.
O que estou fazendo errado?
fonte
--pipe
ser ineficiente? Quero dizer, é algum tipo de problema fundamental ou mais específico da implementação.--pipe
cada byte único precisa passar pelo processo único, que precisa processar um pouco em cada byte. A--pipepart
maioria dos bytes nunca é vista pelo processo central: eles são processados por trabalhos gerados. Como são poucas as linhas que constituem o gargalo,--pipe
eu gostaria de receber um codificador C / C ++ que reescrevesse a parte que seria executada para as pessoas que possuem o compilador C no caminho.grep é muito eficaz - não há sentido em executá-lo em paralelo. No seu comando, apenas a descompressão precisa de mais CPU, mas isso não pode ser paralelo.
A divisão da entrada por paralelo precisa de mais CPU do que a obtenção de linhas correspondentes por grep.
A mudança de situação se você deseja usar, em vez de grep, algo que precisa de muito mais CPU para cada linha - então paralelo teria mais sentido.
Se você deseja acelerar esta operação - veja onde estão os gargalos - provavelmente é descompactação (ajuda a usar outra ferramenta de descompressão ou melhor CPU) ou - leitura do disco (ajuda a usar outra ferramenta de descompressão ou sistema de disco melhor).
Pela minha experiência - às vezes é melhor usar o lzma (-2 por exemplo) para compactar / descompactar arquivos - ele tem uma compactação mais alta que o gzip, portanto, menos dados precisam ser lidos do disco e a velocidade é comparável.
fonte
A descompressão é o gargalo aqui. Se a descompressão não for paralelizada internamente, você não conseguirá isso sozinha. Se você tiver mais de um trabalho como esse, é claro iniciá-los em paralelo, mas é difícil paralelizar seu pipeline por si só. Dividir um fluxo em fluxos paralelos quase nunca vale a pena e pode ser muito doloroso com a sincronização e a mesclagem. Às vezes, você apenas precisa aceitar que vários núcleos não ajudarão em todas as tarefas que você está executando.
Em geral, a paralelização no shell deve estar principalmente no nível de processos independentes.
fonte
parallel
. Concordo que certamente está no primeiro caso (sem paralelo), mas no segundo (com paralelo) o gargalo está no lado paralelo. Isso decorre da observação de que a taxa de transferência cai significativamente, conforme medido porpv
. Se o gargalo estiver em descompressão, a taxa de transferência não mudará o que você adicionar ao pipeline. É uma definição muito intuitiva de taxa de transferência, eu acho - a coisa que mais limita a taxa de transferência.parallel
pode gravar no seu pipe. Nesse caso, a maioria dosgrep
processos simplesmente espera obter mais, enquantoparallel
trabalha o tempo todo para multiplexar os blocos em vários pipes (que são operações de E / S extras e podem até bloquear a descompressão, se o buffer estiver cheio). Você também tentou brincar com o--block
parâmetro? O padrão é que1M
, até que um grep obtenha1M
dados, o restante quase certamente já está concluído. Portanto, voltamos ao fato de que não faz sentido paralelizar isso.-N
/-L
opções. Parece que as opções padrão estão muito perto de ótimo local que eu experimentar :)pv
(comtime
). Dessa forma, você pode ver sepv
está diminuindo a velocidade. Se for,parallel
copiar dados em pipes é uma sobrecarga adicional. E, de qualquer forma, tenho certeza de quegrep
é quase em tempo real nesse caso, especialmente se o padrão for uma sequência simples sem muito retorno. Além disso,parallel
irá intercalar e atrapalhar asgrep
saídas.pv
se isso não causa o problema, obrigado pelo conselho.