Quero fazer algumas simulações usando uma ferramenta Python que fiz. O problema é que eu teria que chamá-lo várias vezes com diferentes parâmetros/argumentos e tudo mais.
Por enquanto, estou usando vários for
loops para a tarefa, como:
for simSeed in 1 2 3 4 5
do
for launchPower in 17.76 20.01 21.510 23.76
do
python sim -a $simSeed -p $launchPower
done
done
Para que as simulações sejam executadas simultaneamente, adiciono um &
no final da linha onde chamo o simulador.
python sim -a $simSeed -p $launchPower &
Usando este método, posso executar várias dessas sementes. No entanto, como meu computador tem memória limitada, quero reescrever o script acima para que ele inicie o for
loop interno paralelamente e o for
loop externo sequencialmente.
Por exemplo, para simSeed = 1
, quero que 5 processos diferentes sejam executados com launchPower
igual a 17.76 20.01 21.510 23.76
. Assim que esta parte for concluída, quero que o script seja executado simSeed = 2
novamente em 5 processos paralelos diferentes launchPower
iguais a 17.76 20.01 21.510 23.76
.
Como posso realizar esta tarefa?
TLDR:
Quero que o loop externo seja executado sequencialmente e o loop interno seja executado paralelamente, de modo que, quando o último processo paralelo do loop interno terminar, o loop externo passe para a próxima iteração.
Responder1
O paralelo GNU tem várias opções para limitar o uso de recursos ao iniciar trabalhos em paralelo.
O uso básico para dois loops aninhados seria
parallel python sim -a {1} -p {2} ::: 1 2 3 4 5 ::: 17.76 20.01 21.510 23.76
Se você quiser lançar no máximo 5 trabalhos ao mesmo tempo, por exemplo, você poderia dizer
parallel -j5 python <etc.>
Alternativamente, você pode usar a --memfree
opção para iniciar novos trabalhos somente quando houver memória suficiente livre, por exemplo, pelo menos 256 MByte
parallel --memfree 256M python <etc.>
Observe que a última opção eliminará o trabalho iniciado mais recentemente se a memória cair abaixo de 50% do valor de "reserva" declarado (mas será requisitado automaticamente para atualização).
Responder2
Conforme mencionado nos comentários, é exatamente para isso que parallel
serve o GNU:
for simSeed in 1 2 3 4 5
do
## Launch 5 instances in parallel
parallel -j5 python sim -a $simSeed -p {} ::: 17.76 20.01 21.510 23.76
done
Responder3
Você poderia armazenar os respectivos IDs dos processos e wait
para que eles finalizassem:
for simSeed in {1..5}; do
pids=()
for launchPower in 17.76 20.01 21.510 23.76; do
python sim -a $simSeed -p $launchPower &
pids+=($!)
done
wait ${pids[@]}
done
pids
é uma matriz de IDs de processos dos trabalhos em segundo plano do loop interno. Com ${pids[@]}
todos os elementos do array são passados para o comando wait.