У меня есть два скрипта, которые используют GPU и обучают модели ML. Я хочу запустить их перед сном, чтобы они работали ночью, и я ожидаю увидеть какие-то результаты утром.
Но поскольку память графического процессора ограничена, я хочу запускать их последовательно, а не параллельно.
Я могу сделать это с помощью python train_v1.py && python train_v2.py
; но, скажем, я начал обучать train_v1
. Тем временем, поскольку обучение занимает много времени, я начал и закончил реализацию второго скрипта, train_v2.py
, и хочу запустить его автоматически, когда python train_v1.py
он будет завершен.
Как мне этого добиться? Спасибо.
решение1
Вот подход, который не подразумевает цикл и проверку того, активен ли еще другой процесс, или вызов train_v1.py
способом, отличным от того, который вы обычно делаете:
$ python train_v1.py
^Z
[1]+ Stopped python train_v1.py
$ % && python train_v2.py
Это ^Z
я нажимаю Ctrl+ Z, когда процесс засыпает, train_v1.py
посылая ему SIGTSTP
сигнал. Затем я говорю оболочке разбудить его с помощью %
, используя его как команду, к которой я могу добавить && python train_v2.py
в конце. Это заставляет его вести себя так же, как если бы вы сделали это python train_v1.py && python train_v2.py
с самого начала.
Вместо %
, вы также можете использовать fg
. Это то же самое. Если вы хотите узнать больше об этих типах функций оболочки, вы можете прочитать о них враздел «УПРАВЛЕНИЕ ЗАДАНИЯМИ» на странице руководства bash.
EDIT: Как продолжать добавлять в очередь
Как отметил jamesdlin в комментарии, если вы попытаетесь продолжить шаблон, train_v3.py
например, добавить до начала v2, вы обнаружите, что не сможете:
$ % && python train_v2.py
^Z
[1]+ Stopped python train_v1.py
train_v1.py
Останавливается только потому train_v2.py
, что не был запущен, а остановить/приостановить/перевести в спящий режим то, что еще не запущено, невозможно.
$ % && python train_v3.py
приведет к тому же результату, что и
python train_v1.py && python train_v3.py
поскольку %
соответствует последнему приостановленному процессу. Вместо того, чтобы пытаться добавлять v3
так, следует использовать историю:
$ !! && python train_v3.py
% && python train_v2.py && python train_v3.py
Можно выполнить расширение истории, как указано выше, или вызвать последнюю команду с помощью сочетания клавиш (например, up) и добавить v3 в конец.
$ % && python train_v2.py && python train_v3.py
Это то, что можно повторять, чтобы добавить что-то еще в конвейер.
$ !! && 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
решение2
Если вы уже запустили python train_v1.py
, вы, возможно, могли бы использовать pgrep
опрос этого процесса до тех пор, пока он не исчезнет, а затем запустить второй скрипт Python:
while pgrep -u "$USER" -fx 'python train_v1.py' >/dev/null
do
# sleep for a minute
sleep 60
done
python train_v2.py
Используя -f
and, -x
вы сопоставляете точную командную строку, которая использовалась для запуска первого скрипта Python. В некоторых системах pgrep
реализует -q
опцию, которая делает его тихим (как и grep -q
), что означает, что перенаправление на /dev/null
не понадобится.
Эта -u
опция ограничивает соответствие тем командам, которые запускаете вы (а не ваш друг или другой человек в той же системе).
Если вы еще не приступили к первому скрипту:
Как упоминалось в комментариях, вы можете просто запустить второй скрипт сразу после первого. Тот факт, что второй скрипт не существует или еще не готов к запуску, не имеет значения (при условии, что он готов к запуску, когда первый скрипт завершится):
python train_v1.py; python train_v2.py
Если сделать это таким образом, второй скрипт запустится независимо от статуса выхода первого скрипта. Использование &&
вместо ;
, как вы показываете в вопросе, также будет работать, но потребует успешного завершения первого скрипта для запуска второго скрипта.
решение3
Вы можете запустить первый скрипт с помощью
python train_v1.py; touch finished
Затем просто создайте цикл, который регулярно проверяет, finished
существует ли:
while [ ! -f finished ] ; do
sleep 5
done
python train_v2.py
rm finished
решение4
Если вам не нужно знать статус завершения первого скрипта, то я рекомендую что-то вродечто написал Кусалананда.
Если вам действительно нужно знать статус выхода (в данном случае вы его, вероятно, не знаете, но кто-то другой может поискать решение, которое это делает), то это сложнее. Я написалнебольшая утилита Linuxpwait
который позволяет дождаться завершения процесса и узнать его статус выхода.