Quero processar muitos arquivos e, como aqui tenho vários núcleos, quero fazê-lo em paralelo:
for i in *.myfiles; do do_something $i `derived_params $i` other_params; done
Conheço uma solução Makefile , mas meus comandos precisam dos argumentos da lista de globbing do shell. O que eu encontrei é:
> function pwait() {
> while [ $(jobs -p | wc -l) -ge $1 ]; do
> sleep 1
> done
> }
>
Para usá-lo, basta colocar e após os trabalhos e uma chamada em espera, o parâmetro fornece o número de processos paralelos:
> for i in *; do
> do_something $i &
> pwait 10
> done
Mas isso não funciona muito bem, por exemplo, eu tentei com, por exemplo, um loop for convertendo muitos arquivos, mas com erros e deixando os trabalhos desfeitos.
Não posso acreditar que isso ainda não tenha sido feito, já que a discussão na lista de discussão do zsh já é antiga. Então você conhece melhor?
bash
shell
zsh
parallel-processing
matemática
fonte
fonte
echo "DONE"
após o loop, que era executado antes dos trabalhos ativos não serem concluídos. => Isso me fez pensar que os trabalhos não foram feitos.Respostas:
Um makefile é uma boa solução para o seu problema. Você pode programar essa execução paralela em um shell, mas é difícil, como você notou. Uma implementação paralela do make não apenas cuida do início dos trabalhos e detecta sua terminação, mas também lida com o balanceamento de carga, o que é complicado.
O requisito de globbing não é um obstáculo: existem implementações que o apóiam. GNU make, que possui expansão de curinga como
$(wildcard *.c)
e acesso ao shell como$(shell mycommand)
(funções de pesquisa no GNU make manual para mais informações). É o padrãomake
no Linux e está disponível na maioria dos outros sistemas. Aqui está um esqueleto do Makefile que você pode adaptar às suas necessidades:Execute algo como
make -j4
executar quatro tarefas em paralelo oumake -j -l3
manter a carga média em torno de 3.fonte
Não tenho certeza de como são seus argumentos derivados. Mas com o GNU Parallel http: // www.gnu.org/software/parallel/, você pode fazer isso para executar um trabalho por núcleo de CPU:
Se o que você deseja derivar é simplesmente alterar a extensão. {{}} Pode ser útil:
Assista ao vídeo de introdução ao GNU Parallel em http://www.youtube.com/watch?v=OpaiGYxkSuQ
fonte
Usar o
wait
comando do shell não funcionaria para você?Seu loop executa um trabalho, espera por ele e executa o próximo trabalho. Se o acima não funcionar para você, o seu poderá funcionar melhor se você seguir
pwait
em frentedone
.fonte
for
loops aninhados para limitar isso:for file in *; do for i in {1..10}; do do_something "$i" & done; wait; done
(não testado) Isso deve fazer dez de cada vez e esperar até que todos os dez de cada grupo estejam concluídos antes de iniciar os próximos dez. Seu loop faz um de cada vez,&
discutindo. Veja a pergunta à qual o JRobert se vinculou para outras opções. Procure no Stack Overflow outras perguntas semelhantes às suas (e essa).for i in *
. Ele teria que passar argumentos para o circuito com um cano ou algo assim. Então, em vez de um loop interno, você pode executar um contador de incremento e executar"micro-"wait"-s"
cada "$ ((i% 32))" -eq '0'wait
com um loop interno do contador funcionou bem para mim. Obrigado!Por que ninguém mencionou xargs ainda?
Supondo que você tenha exatamente três argumentos,
Caso contrário, use um delimitador (nulo é útil para isso):
EDIT: para o exposto, cada parâmetro deve ser separado por um caractere nulo e, em seguida, o número de parâmetros deve ser especificado com o xargs -n.
fonte
Eu tentei algumas das respostas. Eles tornam o script um pouco mais complexo do que o necessário. O ideal é usar
parallel
ouxargs
seria preferível, no entanto, se as operações dentro do loop for forem complicadas, pode ser problemático criar arquivos de linhas grandes e longas para fornecer em paralelo. em vez disso, poderíamos usar a fonte da seguinte formaAssim, para a sua solução de problemas, seria
definir fazer algo como
do_something.sh
}
executar com
xarg
ougnu parallel
Presumo que a independência funcional das iterações de for esteja implícita.
fonte