Estamos discutindo como implementar exatamente esse recurso na lista de discussão do GNU Parallel agora link
Sinta-se à vontade para participar: link
Um protótipo está pronto para testes: link
tee
encaminha seu stdin para cada arquivo especificado, enquanto pee
faz o mesmo, mas para pipes. Esses programas enviam cada linha do seu stdin para cada arquivo / pipe especificado.
No entanto, eu estava procurando uma maneira de "load balance" o stdin para diferentes pipes, então uma linha é enviada para o primeiro pipe, outra para o segundo, etc. Também seria bom se o stdout do tubos são coletados em um fluxo também.
O caso de uso é uma simples paralelização de processos intensivos de CPU que funcionam linha a linha. Eu estava fazendo um sed
em um arquivo de 14GB, e poderia ter rodado muito mais rápido se eu pudesse usar vários processos sed
. O comando foi assim:
pv infile | sed 's/something//' > outfile
Para paralelizar, o melhor seria se o paralelo GNU suportasse essa funcionalidade como tal (criado a opção --demux-stdin
):
pv infile | parallel -u -j4 --demux-stdin "sed 's/something//'" > outfile
No entanto, não há nenhuma opção como esta e parallel
sempre usa seu stdin como argumentos para o comando que invoca, como xargs
. Então eu tentei isso, mas é irremediavelmente lento, e está claro o porquê:
pv infile | parallel -u -j4 "echo {} | sed 's/something//'" > outfile
Eu só queria saber se há outra maneira de fazer isso (menos de codificar isso). Se houvesse um "equilíbrio de carga" tee
(vamos chamá-lo de lee
), eu poderia fazer isso:
pv infile | lee >(sed 's/something//' >> outfile) >(sed 's/something//' >> outfile) >(sed 's/something//' >> outfile) >(sed 's/something//' >> outfile)
Não é bonita, então eu definitivamente prefiro algo como a versão parallel
, mas isso também funcionaria.
Eu olharia para implementar isso em Perl com Parallel :: ForkManager . Você poderia fazer a divisão de linha no script e depois alimentar as linhas resultantes nos processos Parallel :: ForkManager. O uso do retorno de chamada run_on_finish
para coletar a saída. Obviamente, para o seu exemplo de sed você poderia apenas fazer a operação de texto em perl e talvez usar algo como AnyEvent para lidar com o paralelismo.