Bash bucles/comandos consecutivos y paralelos

Bash bucles/comandos consecutivos y paralelos

Quiero ejecutar algunas simulaciones usando una herramienta Python que hice. El problema es que tendría que llamarlo varias veces con diferentes parámetros/argumentos y todo.

Por ahora, estoy usando múltiples forbucles para la tarea, 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 las simulaciones se ejecuten simultáneamente, agrego un &al final de la línea donde llamo al simulador.

python sim -a $simSeed -p $launchPower &

Con este método puedo ejecutar varias semillas de este tipo. Sin embargo, dado que mi computadora tiene memoria limitada, quiero reescribir el script anterior para que inicie el forbucle interno en paralelo y el forbucle externo de forma secuencial.

Como ejemplo, para simSeed = 1, quiero que se ejecuten 5 procesos diferentes con launchPowerigual a 17.76 20.01 21.510 23.76. Tan pronto como se complete esta parte, quiero que el script se ejecute una simSeed = 2y otra vez 5 procesos paralelos diferentes con launchPowerigual a 17.76 20.01 21.510 23.76.

¿Cómo puedo lograr esta tarea?

TLDR:

Quiero que el bucle externo se ejecute secuencialmente y el bucle interno se ejecute en paralelo, de modo que cuando finalice el último proceso paralelo del bucle interno, el bucle externo pase a la siguiente iteración.

Respuesta1

GNU paralelo tiene varias opciones para limitar el uso de recursos al iniciar trabajos en paralelo.

El uso básico para dos bucles anidados sería

parallel python sim -a {1} -p {2} ::: 1 2 3 4 5 ::: 17.76 20.01 21.510 23.76

Si desea iniciar como máximo 5 trabajos al mismo tiempo, por ejemplo, podría decir

parallel -j5 python <etc.>

Alternativamente, puede utilizar la --memfreeopción para iniciar nuevos trabajos sólo cuando haya suficiente memoria libre, por ejemplo, al menos 256 MByte.

parallel --memfree 256M python <etc.>

Tenga en cuenta que la última opción finalizará el trabajo iniciado más recientemente si la memoria cae por debajo del 50 % del valor de "reserva" indicado (pero se volverá a solicitar para ponerse al día automáticamente).

Respuesta2

Como se menciona en los comentarios, esto es exactamente para lo que parallelsirve 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

Respuesta3

Podrías almacenar los respectivos ID de proceso y waitpara que finalicen:

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

pidses una matriz de ID de proceso de los trabajos en segundo plano del bucle interno. Con ${pids[@]}todos los elementos de la matriz se pasan al comando de espera.

información relacionada