如何调试

Dask jobqueue 由多位贡献者开发和测试,每位贡献者都有一套特定的 HPC 系统设置:特定版本的作业调度器运行在特定的操作系统上。因此,在某些特定情况下,它可能无法在您的系统上直接工作。本节提供了一些提示,帮助您确定可能出现的问题。

检查作业脚本

Dask-jobqueue 向您的队列系统提交“作业脚本”(参见工作原理)。检查这些脚本通常可以发现您的 Cluster 对象配置中的错误,或者您的作业调度器可能不接受的指令,特别是包含 #PBS#SBATCH 或等效行的头部。在创建集群对象后,可以轻松完成此操作

print(cluster.job_script())

如果作业脚本中的所有内容看起来都正确,下一步是尝试使用该脚本提交一个测试作业。您可以简单地将打印的内容复制并粘贴到一个真实的作业脚本文件中,然后使用 qsubsbatchbsub 或适用于您的作业队列系统的命令提交它。

要纠正此时检测到的任何问题,您可以在初始化集群对象时尝试使用 job_extra_directivesjob_script_prologue 参数。

特别要注意用于启动 worker 的 python 可执行文件,它默认是用于启动 scheduler 的那个(这仅当 python 位于 Dask scheduler 和 Dask worker 都可以访问的共享位置时才有意义)。您可以在 SLURMCluster 中使用 python 参数指定您希望用于启动 worker 的 python 可执行文件。

即使您刚刚加载了正确的模块,您可能看到的典型错误是 ModuleNotFoundError

Loading tensorflow-gpu/py3/2.1.0
  Loading requirement: cuda/10.1.2 cudnn/10.1-v7.5.1.10 nccl/2.5.6-2-cuda
    gcc/4.8.5 openmpi/4.0.2-cuda
distributed.nanny - INFO -         Start Nanny at: 'tcp://10.148.3.252:39243'
distributed.dashboard.proxy - INFO - To route to workers diagnostics web server please install jupyter-server-proxy: python -m pip install jupyter-server-proxy
distributed.worker - INFO -       Start worker at:   tcp://10.148.3.252:42618
distributed.worker - INFO -          Listening to:   tcp://10.148.3.252:42618
distributed.worker - INFO -          dashboard at:         10.148.3.252:36903
distributed.worker - INFO - Waiting to connect to:    tcp://10.148.0.20:35926
distributed.worker - INFO - -------------------------------------------------
distributed.worker - INFO -               Threads:                          1
distributed.worker - INFO -                Memory:                   10.00 GB
distributed.worker - INFO -       Local Directory: <local-dir>
distributed.worker - INFO - -------------------------------------------------
distributed.worker - INFO -         Registered to:    tcp://10.148.0.20:35926
distributed.worker - INFO - -------------------------------------------------
distributed.core - INFO - Starting established connection
distributed.worker - WARNING -  Compute Failed
Function:  train_dense_model
args:      (None, False, 64)
kwargs:    {}
Exception: ModuleNotFoundError("No module named 'tensorflow'")

slurmstepd: error: *** JOB 1368437 ON <node> CANCELLED AT 2020-04-10T17:14:30 ***
distributed.worker - INFO - Connection to scheduler broken.  Reconnecting...
distributed.worker - INFO - Stopping worker at tcp://10.148.3.252:42618
distributed.nanny - INFO - Worker closed

当您使用与您希望用于 worker 的 python 不同(此处为 module load python/3.8.5)的 python 创建集群时,就会发生这种情况,产生的作业脚本如下(请注意最后一行,它将显示使用了哪个 python

#!/usr/bin/env bash

#SBATCH -J <job_name>
#SBATCH -n 1
#SBATCH --cpus-per-task=10
#SBATCH --mem=10G
#SBATCH -t 1:00:00
#SBATCH --gres=gpu:1
#SBATCH --qos=qos_gpu-dev
#SBATCH --distribution=block:block
#SBATCH --hint=nomultithread
#SBATCH --output=%x_%j.out
module purge
module load tensorflow-gpu/py3/2.1.0
/path/to/anaconda-py3/2019.10/bin/python -m distributed.cli.dask_worker tcp://10.148.0.20:44851 --nthreads 1 --memory-limit 10.00GB --name name --nanny --death-timeout 60 --interface ib0

激活调试模式

Dask-jobqueue 使用 Python logging 模块。为了更好地理解内部发生的情况,您可能需要激活日志显示。这可以通过在您的脚本或 notebook 中运行此行 python 代码来完成

import logging
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG)

与您的作业队列系统交互

如上所述,每个 worker 都在一个批处理作业中启动。查询您的作业队列系统会非常有帮助。您可能需要检查的一些事项

  • 是否有与 dask-jobqueue 相关的正在运行的作业?

  • 是否有已完成的作业、错误作业?

  • dask-jobqueue 作业的标准输出(stdout)或标准错误(stderr)是什么?

您可能需要查看的其他事项

从这里开始会变得有点复杂。一些其他已经出现过的问题如下

  • dask-jobqueue 中使用的提交命令(qsub 或等效命令)与您使用的命令不符。在给定的 JobQueueCluster 实现中检查作业提交命令和参数是否与您熟悉,最终尝试它们。

  • 提交命令的输出与 dask-jobqueue 期望的输出不同。我们使用提交命令的标准输出解析与启动的 worker 组对应的 job_id。如果解析失败,则 dask-jobqueue 将无法按预期工作,并可能抛出异常。您可以查看解析函数 JobQueueCluster._job_id_from_submit_output