Estou tentando processar a entrada de diferentes maneiras em paralelo, escrevendo as linhas resultantes à medida que elas chegam. Minha abordagem atual é esta:
# process_parallel.sh
read input
parallel --colsep ' ' --linebuffer 'echo $input | {}' \
::: 'python process1.py' ./process2.sh ./process3
O contexto se resume a algo assim:
(sleep 1; echo "short input arriving late") | ./process_parallel.sh | ./collate_results.sh
O procedimento acima funciona, mas tem uma desvantagem importante: os processos não são iniciados até que a entrada seja lida. Quero iniciá-los imediatamente, pois isso pode demorar um pouco e, em seguida, colocar o canal paralelo em seu stdin completo para cada um deles.
Como faço para conseguir isso?
Responder1
Muito trabalho foi colocado no GNU Parallel para evitar que ele iniciasse um novo trabalho, a menos que houvesse dados para execução. Isso ocorre porque alguns programas falham muito se não receberem nenhuma entrada. Então você estará trabalhando contra o design do GNU Parallel.
Para duplicar a entrada você pode usar tee
e processar a substituição:
cat namedpipe_or_file | tee >(process1) >(process2) >(process3) >/dev/null
Ele começará process1
, process2
e process3
imediatamente. A saída pode, no entanto, ser misturada, portanto, se a saída precisar ser usada, você deverá redirecioná-la para arquivos diferentes:
cat namedpipe_or_file | tee >(process1 > out1) >(process2 > out2) >(process3 > out3) >/dev/null
Responder2
Tenha dois scripts wrapper: primeiro, modifique process_parallel.sh para que cada um dos processos seja instruído a ler sua entrada, de três arquivos, digamos arquivo1, arquivo2, arquivo3.
Agora escreva um segundo script wrapper que envie paralelamente sua entrada padrão para os três arquivos, algo como:
#!/bins/bash
#parallelise input
# let's call this file parallelise
parallel -j 3 -- "echo $1 > file1" "echo $1 > file2" "echo $1 file3"
Agora você começa suas coisas com:
./process_parallel_sh; cat InputFile | parallelise;
Responder3
Parallel tem uma --tee
opção, que pode ser usada assim:
(sleep 1; echo "short input arriving late") |\
parallel --colsep ' ' --linebuffer --pipe --tee ::: 'python process1.py' ./process2.sh ./process3 |\
./collate_results.sh