Executando várias instâncias do perl via xargs

5

Eu tenho um script dataProcessing.pl que aceita um arquivo .txt delimitado por tabulação e executa tarefas de processamento extensivas nos dados contidos. Existem vários arquivos de entrada ( file1.txt file2.txt file3.txt ) que estão atualmente em loop como parte de um script bash, que invoca o perl durante cada iteração (ou seja, os arquivos de entrada são processados um de cada vez).

No entanto, desejo executar várias instâncias do Perl (se possível) e processar todos os arquivos de entrada simultaneamente via xargs. Estou ciente de que você pode executar algo parecido com:

perl -e 'print "Test" x 100' | xargs -P 100

No entanto, quero passar um arquivo diferente para cada instância paralela de Perl aberta (uma instância funciona em file1.txt, uma trabalha em file2.txt e assim por diante). Identificador de arquivo ou caminho de arquivo pode ser passado para Perl como um argumento. Como posso fazer isso? Eu não sei como eu passaria os nomes dos arquivos para xargs, por exemplo.

    
por AnnaSchumann 26.03.2018 / 19:11

3 respostas

11

Use xargs com -n 1 significando "apenas passe um único argumento para cada invocação do utilitário".

Algo como:

printf '%s\n' file*.txt | xargs -n 1 -P 100 perl dataProcessing.pl

que assume que os nomes dos arquivos não contêm novas linhas literais.

Se você tiver o GNU xargs ou uma implementação de xargs que entenda -0 (para ler argumentos delimitados por nul, que permite nomes de arquivos com novas linhas) e -r (por não executar o utilitário com vazio lista de argumentos, quando file*.txt não corresponde a nada e nullglob está em vigor), você pode fazer

printf '%s
printf '%s\n' file*.txt | xargs -n 1 -P 100 perl dataProcessing.pl
' file*.txt | xargs -r0 -n 1 -P 100 perl dataProcessing.pl

Observe que essas duas variações podem iniciar até 100 instâncias paralelas do script, o que pode não ser o que você deseja. Você pode querer limitá-lo a um número razoável relacionado ao número de CPUs em sua máquina (ou relacionado à quantidade total de RAM disponível dividida pelo uso esperado de memória por tarefa, se estiver ligado à memória).

    
por 26.03.2018 / 19:14
5

Não há necessidade de ficar chique aqui. Em seu bash for-loop, apenas o plano de fundo do processo perl:

for f in file*.txt; do
    perl dataProcessing.pl "$f" &
done
# wait for them to complete
wait
echo "All done."
    
por 26.03.2018 / 19:31
2

O GNU Parallel é feito exatamente para isso:

parallel some_command {} ::: *.txt

O padrão é um trabalho por núcleo da CPU. Se você deseja executar 100 trabalhos em paralelo:

parallel -j100 some_command {} ::: *.txt

Conhecendo o Perl, você se sentirá em casa usando até mesmo os recursos mais avançados do GNU Parallel. O que você acha que isso faz:

parallel echo '{= s/(\d+)/$1*2/e; s/(.)/uc($1)/e; s/bar/baz/; s/foo/bar/ =}' \
  ::: 'my foo' 'i went to a baraar to get a 12" crowfoo'

O GNU Parallel é um paralelizador geral e facilita a execução de trabalhos em paralelo na mesma máquina ou em várias máquinas para as quais você tem acesso ssh.

Se você tem 32 tarefas diferentes que você quer rodar em 4 CPUs, uma forma direta de paralelizar é rodar 8 tarefas em cada processador:

O

GNUParallelgeraumnovoprocessoquandoumtermina-mantendoasCPUsativaseeconomizandotempo:

Instalação

Por razões de segurança, você deve instalar o GNU Parallel com seu gerenciador de pacotes, mas se o GNU Parallel não estiver empacotado para sua distribuição, você pode fazer uma instalação pessoal, que não requer acesso root. Isso pode ser feito em 10 segundos ao fazer isso:

(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash

Para outras opções de instalação, consulte o link

Saiba mais

Veja mais exemplos: link

Assista aos vídeos de introdução: link

Percorra o tutorial: link

Inscreva-se na lista de e-mail para obter suporte: link

    
por 27.03.2018 / 19:36