Tengo dos scripts que usan GPU y entrenan modelos de ML. Quiero empezar a usarlos antes de irme a dormir para que funcionen por la noche y espero ver algunos resultados por la mañana.
Pero debido a que la memoria de la GPU es limitada, quiero ejecutarlos en serie en lugar de en paralelo.
Puedo hacerlo con python train_v1.py && python train_v2.py
; pero digamos que comencé a entrenar el train_v1
. Mientras tanto, debido a que la capacitación lleva mucho tiempo, comencé y terminé la implementación del segundo script train_v2.py
y quiero ejecutarlo automáticamente cuando python train_v1.py
esté terminado.
¿Cómo puedo lograr eso? Gracias.
Respuesta1
Este es un enfoque que no implica realizar bucles y verificar si el otro proceso todavía está activo, o llamar train_v1.py
de una manera diferente a la que haría normalmente:
$ python train_v1.py
^Z
[1]+ Stopped python train_v1.py
$ % && python train_v2.py
Soy ^Z
yo presionando Ctrl+ Zmientras el proceso se ejecuta para dormir train_v1.py
enviándole una SIGTSTP
señal. Luego, le digo al shell que lo active con %
, usándolo como un comando al que puedo agregar && python train_v2.py
al final. Esto hace que se comporte tal como si lo hubieras hecho python train_v1.py && python train_v2.py
desde el principio.
En lugar de %
, también puedes usar fg
. Es lo mismo. Si desea obtener más información sobre este tipo de características del shell, puede leer sobre ellas enla sección "CONTROL DE TRABAJO" de la página de manual de bash.
EDITAR: Cómo seguir agregando a la cola
Como señaló jamesdlin en un comentario, si intenta continuar con el patrón para agregarlo, train_v3.py
por ejemplo, antes de que comience la versión 2, encontrará que no puede:
$ % && python train_v2.py
^Z
[1]+ Stopped python train_v1.py
Sólo train_v1.py
se detiene porque train_v2.py
no ha comenzado, y no se puede detener/suspender/dormir algo que ni siquiera ha comenzado.
$ % && python train_v3.py
resultaría en lo mismo que
python train_v1.py && python train_v3.py
porque %
corresponde al último proceso suspendido. En lugar de intentar agregar v3
algo así, uno debería usar el historial:
$ !! && python train_v3.py
% && python train_v2.py && python train_v3.py
Se puede hacer una expansión del historial como se muestra arriba, o recuperar el último comando con una combinación de teclas (como arriba) y agregar v3 al final.
$ % && python train_v2.py && python train_v3.py
Eso es algo que se puede repetir para agregar más al proyecto.
$ !! && python train_v3.py
% && python train_v2.py && python train_v3.py
^Z
[1]+ Stopped python train_v1.py
$ !! && python train_v4.py
% && python train_v2.py && python train_v3.py && python train_v4.py
Respuesta2
Si ya ha comenzado python train_v1.py
, posiblemente podría utilizar pgrep
para sondear ese proceso hasta que desaparezca y luego ejecutar su segundo script de Python:
while pgrep -u "$USER" -fx 'python train_v1.py' >/dev/null
do
# sleep for a minute
sleep 60
done
python train_v2.py
Al usar -f
y -x
usted compara la línea de comando exacta que se usó para iniciar el primer script de Python. En algunos sistemas, pgrep
implementa una -q
opción que lo hace silencioso (al igual que ), lo que significa que no sería necesaria grep -q
la redirección a ./dev/null
La -u
opción restringe la coincidencia a los comandos que estás ejecutando (y no a un amigo u otra persona en el mismo sistema).
Si aún no has iniciado el primer script:
Como se mencionó en los comentarios, puede iniciar el segundo script inmediatamente después del primero. El hecho de que el segundo script no exista, o que aún no esté listo para ejecutarse, no importa (siempre que esté listo para ejecutarse cuando finalice el primer script):
python train_v1.py; python train_v2.py
Al hacerlo de esta manera, se iniciará el segundo script independientemente del estado de salida del primer script. Usar &&
en lugar de ;
, como muestra en la pregunta, también funcionará, pero requerirá que el primer script finalice correctamente para que se inicie el segundo script.
Respuesta3
Puede iniciar el primer script con
python train_v1.py; touch finished
Luego simplemente haga un bucle que verifique periódicamente si finished
existe:
while [ ! -f finished ] ; do
sleep 5
done
python train_v2.py
rm finished
Respuesta4
Si no necesita saber el estado de salida del primer script, le recomiendo algo comolo que escribió Kusalananda.
Si necesita conocer el estado de salida (lo cual probablemente no sea necesario en este caso, pero puede que alguien más venga buscando una solución que lo haga), es más complicado. he escrito unpequeña utilidad de Linuxpwait
que le permite esperar a que finalice un proceso y conocer su estado de salida.