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 for
bucles 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 for
bucle interno en paralelo y el for
bucle externo de forma secuencial.
Como ejemplo, para simSeed = 1
, quiero que se ejecuten 5 procesos diferentes con launchPower
igual a 17.76 20.01 21.510 23.76
. Tan pronto como se complete esta parte, quiero que el script se ejecute una simSeed = 2
y otra vez 5 procesos paralelos diferentes con launchPower
igual 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 --memfree
opció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 parallel
sirve 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 wait
para 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
pids
es 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.