Bash loops/comandos consecutivos e paralelos

Bash loops/comandos consecutivos e paralelos

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 forloops 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 forloop interno paralelamente e o forloop externo sequencialmente.

Por exemplo, para simSeed = 1, quero que 5 processos diferentes sejam executados com launchPowerigual a 17.76 20.01 21.510 23.76. Assim que esta parte for concluída, quero que o script seja executado simSeed = 2novamente em 5 processos paralelos diferentes launchPoweriguais 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 --memfreeopçã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 parallelserve 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 waitpara 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.

informação relacionada