Sequencial: for i in {1..1000}; do do_something $i; done
- muito lento
Paralelo: for i in {1..1000}; do do_something $i& done
- muita carga
Como executar comandos em paralelo, mas não mais do que, por exemplo, 20 instâncias por momento?
Agora geralmente usando o hack like for i in {1..1000}; do do_something $i& sleep 5; done
, mas essa não é uma boa solução.
Atualização 2 : converteu a resposta aceita em um script: http://vi-server.org/vi/parallel
#!/bin/bash
NUM=$1; shift
if [ -z "$NUM" ]; then
echo "Usage: parallel <number_of_tasks> command"
echo " Sets environment variable i from 1 to number_of_tasks"
echo " Defaults to 20 processes at a time, use like \"MAKEOPTS='-j5' parallel ...\" to override."
echo "Example: parallel 100 'echo \$i; sleep \`echo \$RANDOM/6553 | bc -l\`'"
exit 1
fi
export CMD="$@";
true ${MAKEOPTS:="-j20"}
cat << EOF | make -f - -s $MAKEOPTS
PHONY=jobs
jobs=\$(shell echo {1..$NUM})
all: \${jobs}
\${jobs}:
i=\$@ sh -c "\$\$CMD"
EOF
Observe que você deve substituir 8 espaços por 2 guias antes de "i =" para fazê-lo funcionar.
parallel
in moreutils não é GNU Parallel e é bastante limitado em suas opções. O comando acima não será executado com o paralelo de moreutils.xargs --max-procs=20
.Não é uma solução bash, mas você deve usar um Makefile, possivelmente
-l
para não exceder uma carga máxima.Então, para iniciar 20 trabalhos por vez, faça
ou iniciar o maior número possível de tarefas sem exceder uma carga de 5
fonte
echo -e 'PHONY=jobs\njobs=$(shell echo {1..100000})\n\nall: ${jobs}\n\n${jobs}:\n\t\techo $@; sleep `echo $$RANDOM/6553 | bc -l`' | make -f - -j20
Agora parece mais hacky novamente.postando o script na pergunta com formatação:
Observe que você deve substituir 8 espaços por 2 guias antes de "i =".
fonte
Uma ideia simples:
Verifique o módulo 20 e execute o comando shell de espera antes de fazer alguma coisa.
fonte
Você pode usar
ps
para contar quantos processos você está executando e, sempre que isso cai abaixo de um determinado limite, você inicia outro processo.Pseudo-código:
fonte
fonte
while [ `jobs | wc -l` -ge 20]; do
?njobs
duas vezes, eo desempenho é muito importante em scripts shell que as tarefas de execução do sono;)sleep 1
parasleep 0.1
e ele começa a média de njobs para 40-50 em vez de 20. Se houver mais de 20 trabalhos, precisamos esperar que qualquer trabalho seja concluído, e não apenas esperar 1 segundo.você pode fazer assim.
usando pipes nomeados, sempre executa 20 subcascas em paralelo.
Espero que ajude :)
fonte