如何监控正在运行的屏幕会话并在最后一个会话结束后开始新会话?

Posted

技术标签:

【中文标题】如何监控正在运行的屏幕会话并在最后一个会话结束后开始新会话?【英文标题】:How to monitor running screen session and start a new session once last one ended? 【发布时间】:2019-11-12 22:32:55 【问题描述】:

为了运行我的神经网络训练,我使用以下脚本启动不同的训练配置:

NNtrain.sh

#!/bin/bash
echo "Start 1st screen"
screen -dmS NN48001 bash -c '../NNrun.sh NN48001 hyperparam_48_001.json 0 0.5'
echo "Start 2nd screen"
screen -dmS NN480001 bash -c '../NNrun.sh NN480001 hyperparam_48_0001.json 0 0.5'
echo "Start 3rd screen"
screen -dmS NN4800001 bash -c '../NNrun.sh NN4800001 hyperparam_48_00001.json 1 0.5'
echo "Start 4th screen"
screen -dmS NN48000001 bash -c '../NNrun.sh NN48000001 hyperparam_48_000001.json 2 0.5'

NNrun.sh

#!/bin/bash
if [ -f "/opt/anaconda/etc/profile.d/conda.sh" ]; then
    . "/opt/anaconda/etc/profile.d/conda.sh"
    CONDA_CHANGEPS1=false conda activate PyTorchNN
    echo "Activated conda env"
fi
echo $1
python main_broad_FEA.py --hyperparam-json $2 --GPU $3 --varstop $4

现在,我的机器中有 3 个 GPU,并且想批量训练更多网络,即在最后一个训练结束后开始下一次训练。因此,我想监控哪些屏幕会话已关闭(即返回),然后使用刚刚运行的屏幕会话使用的 GPU 启动一个新的屏幕会话。

如何检查我的屏幕会话是否以及哪些会话返回,以便我可以使用 bash 脚本启动下一个会话?

(注意:如果在 bash 脚本中执行此操作不必要地更复杂,那么请随时提出合适的替代方案。)

【问题讨论】:

你为什么要使用screen?脚本是否需要任何手动输入?这看起来像你想使用 xargs -P4 或 GNUs parallel @KamilCuk 谢谢你的回答。我对这两者中的任何一个都没有经验,因此没有想过这样做。我会调查的。 @KamilCuk 问题:有没有办法让我连接到各个并行会话并监控进度?由于我正在训练神经网络,每个线程都是计算密集型的,并且可能运行 30 分钟到数天不等,因此希望能够在训练期间检查中间输出,并在出现问题时中止训练,无需中止所有训练。 在这种情况下,我说要使用screen。你需要分别对每项工作做一些事情,所以就是这样。但是您必须自己编写脚本,编写所有逻辑以“检查哪个进程返回,以便您可以启动下一个进程”。如果需要几天时间,我宁愿创建一个插入式 systemd 服务文件,以便我可以轻松管理(停止/重新启动)它,并且 journald 负责日志记录。我想象你也可以在 systemd 中添加插件服务的依赖项,想知道这是否可以一次性创建整个流程树。 【参考方案1】:
#!/bin/bash

doit() 
    if [ -f "/opt/anaconda/etc/profile.d/conda.sh" ]; then
      . "/opt/anaconda/etc/profile.d/conda.sh"
      CONDA_CHANGEPS1=false conda activate PyTorchNN
      echo "Activated conda env"
    fi
    echo $1
    python main_broad_FEA.py --hyperparam-json $2 --GPU $3 --varstop $4

export -f doit

parallel -j 3 1 2 % 3 ::: a r g 1 ::: a r g 2 ::: a r g 4

解释:

“-j 3”定义作业槽数 “1”被“arg1”中的相应元素替换 - 同样适用于 2 和 3 % 是作业槽号。我们使用它来确定在哪个 GPU 上运行。 (参见https://doi.org/10.5281/zenodo.1146014 第 30 页) ":::" 后跟参数列表(每个作业一个)

如果您想实时监控正在运行的作业,可以使用tmux

parallel --tmux -j 3 1 2 % 3 ::: a r g 1 ::: a r g 2 ::: a r g 4

【讨论】:

嗨@Ole Tange,我很荣幸你回答这个问题。您能否简要说明最后一行发生了什么? @avgJoe 请花 15 分钟阅读第 2 章:doi.org/10.5281/zenodo.1146014,然后详细说明您不理解该行的哪些部分。 我试图添加澄清,如果我误解了什么,请纠正我。但是,这如何处理 GPU 上的负载平衡?它是如何调用 doit() 函数的?鉴于我有一个要处理的任务队列,并且只需在最后释放的 GPU 上启动一个新任务,该命令如何确保发生这种情况?【参考方案2】:

当我在上面提出我的问题时,我的问题过于复杂了。

我最后使用的解决方案是将touch "$3.GPUFREE" 添加到我的 NNrun.sh 脚本的末尾。这会在 NNrun.sh 脚本终止时创建一个空文件“.GPUFREE”。最后,我运行一个循环,检查是否从我的 NNtrain.sh 创建了“.GPUFREE”文件,从而知道哪个 GPU 被释放。然后脚本就删除了该文件并在该 GPU 上开始下一个作业。

【讨论】:

以上是关于如何监控正在运行的屏幕会话并在最后一个会话结束后开始新会话?的主要内容,如果未能解决你的问题,请参考以下文章

使用脚本保持远程会话运行直到程序结束?

如何附加到现有的屏幕会话或创建新的屏幕会话并运行命令?

如何列出正在运行的屏幕会话?

iOS 上的 AVCapture 会话中没有音频

如何计算给定会话日志的峰值并发用户

如何拦截会话结束并获取属性?