一项评估后,许多分散的快工闲置,或者在有更多任务时从不接受任何工作

时间:2019-04-06 01:55:00

标签: python dask dask-distributed

我们正在使用dask来生成设计,然后将其发送给dask工作者,进而使用pytorch进行培训,从而优化深度学习(DL)架构。我们观察到一些工作人员似乎没有开始工作,而那些完成了DL评估的工人并没有立即开始评估下一个等待的DL。

我们已在Oak Ridge国家实验室的Summit超级计算机上实现了此功能。对于我们的原型,我们提交了一个批处理作业,该作业分配了92个节点,启动了一个快速调度程序,以及92个快速工作程序,每个节点专用一个工作程序。每个节点具有6个Nvidia Volta V100,两个IBM Power9和512 GB DDR4 + 96GB HMB @内存。然后,每个工作人员都使用pytorch训练DL并将其验证准确性作为“适合度”返回。但是,如果提出的DL体系结构不可行,则会引发异常,并且相关的适应性变为-MAXINT。

在仅由两名工作人员进行的初始试用运行中,我们注意到,如果一名工作人员评估了格式错误的DL设计,则会立即为其分配新的DL进行评估。直到运行结束,这两个工人中的任何一个都不曾闲着。

这是实际代码的精简版本。

from dask.distributed import Client, as_completed

client = Client(scheduler_file=’scheduler.json’)

# posed_dl_designs is a list of random DL architectures, 
# eval_dl is the entry point for the pytorch training
worker_futures = client.map(eval_dl, posed_dl_designs)

for res in as_completed(worker_futures):
    evaluated_dl = res.result()

    # pool is Queue of evaluated DLs sorted by validation    
    # accuracy; so update_pool() replaces the least accurate DL
    # with the newly evaluated DL
    update_pool(evaluated_dl, pool)

    # Let the workers drain down if we meet some kind of budget
    # for generated DL designs; otherwise generate a new DL and
    # give it to a worker for training/evaluation
    if not stop():

        # create_new_dl() selects one of the better DLs from 
        # the pool, clones it, and alters it slightly, thereby 
        # creating a new DL design
        new_dl = create_new_dl(pool)

        # Now evaluate/train the new DL
        new_future = client.submit(eval_dl, new_dl)
        iterator.add(new_future)

这就是我们调用调度程序和工作程序的方式:

# The scheduler doesn't need GPUs. It just needs one lonely core to run on.
jsrun --gpu_per_rs 0 --nrs 1 --tasks_per_rs 1 --cpu_per_rs 1 --rs_per_host 1 dask-scheduler --interface ib0 --no-bokeh --no-show --scheduler-file $SCHEDULER_FILE &

# Spin up an individual task for each worker. Since dask does not use MPI, specify smpiargs none.
for i in {0..91}; do

    jsrun --smpiargs="none" --nrs 1 -e individual --stdio_stdout ${RUN_DIR}/worker_out.%h.%j.%t.%p --stdio_stderr ${RUN_DIR}/worker_error.%h.%j.%t.%p   --tasks_per_rs 1 --cpu_per_rs 14 --gpu_per_rs 6 --rs_per_host 1 dask-worker --nthreads 1 --nprocs 1 --memory-limit 512e9 --interface ib0 --no-bokeh --reconnect --scheduler-file $SCHEDULER_FILE --resources "MEM=512e9" &

done

# Invocation for the controller process elided

当我们扩大规模以雇用92名工人时,我们发现几分钟后只有5或6名工人在跑-这些相当于拥有可行DL进行训练的工人,这是他们最初的DL设计候选人。

闲散的工人分为两类。显然,大多数闲置的工作人员已经评估了损坏的DL设计,并忠实地返回了适当的特殊值来表示:但是后来从未将新的DL重新分配给现在免费的工作人员。另一类工人从未评估过任何DL,以下是其输出的典型代表:

distributed.nanny - INFO -         Start Nanny at: 'tcp://10.41.18.55:45941'
distributed.diskutils - INFO - Found stale lock file and directory '/gpfs/alpine/csc342/proj-shared/may/delemera_first_trial_run/worker-c4o0rsb3', purging
distributed.worker - INFO -       Start worker at:    tcp://10.41.18.55:44107
distributed.worker - INFO -          Listening to:    tcp://10.41.18.55:44107
distributed.worker - INFO -              nanny at:          10.41.18.55:45941
distributed.worker - INFO - Waiting to connect to:     tcp://10.41.18.54:8786
distributed.worker - INFO - -------------------------------------------------
distributed.worker - INFO -               Threads:                          1
distributed.worker - INFO -                Memory:                  512.00 GB
distributed.worker - INFO -       Local Directory: /gpfs/alpine/csc342/proj-shared/may/delemera_first_trial_run/worker-kqf62513
distributed.worker - INFO - -------------------------------------------------
distributed.worker - INFO -         Registered to:     tcp://10.41.18.54:8786
distributed.worker - INFO - -------------------------------------------------
distributed.core - INFO - Starting established connection

因此,对于那些闲置的此类工人,在与调度程序建立通信时存在问题。我们没有注意到其他可能相关的消息。

1 个答案:

答案 0 :(得分:1)

事实证明,问题不在于dask,而在于我们如何调用代码。

也就是说,我们的顶级脚本中有一个运行时参数,该参数指示发送给工人的初始人口数量。如果未指定默认值,我们的原始实现将使用默认值,并且在工作提交脚本中,我们取消了相应的命令行参数,这意味着默认值5用于初始种群的大小。

如上面的代码片段所示,我们配置设置的方式是,无论分配的工作人员数量或更新的人员池的大小如何,初始人口数量都将决定该数量的增加实际繁忙的工人。也就是说,由于我们使用默认值5,因此这些是调度程序的第一个任务。然后,随着每个工作程序评估一个DL,它将被添加到池中,并且另一个工作程序将被分配一个新的DL进行评估。 (不一定是刚刚完成评估最新DL的工作人员,这是造成混乱的最初原因。)永远不可能将更多的工作分配给剩余的空闲工作人员。

我们现在已删除此参数的默认值,以强制用户为每次运行指定此关键信息。

一些课程包括:

  • 为命令行参数提供默认值可能会变得无声,并且很难找到错误源
  • 花时间为运行时参数添加健全性检查(例如,如果初始人口规模小于池规模,代码现在会抱怨并失败)
  • 不要以为这是从属软件包的错;错误可能出在您自己的代码中
  • 磁盘空间很便宜,因此请真正打开日志记录以获取适当且有用的诊断信息
  • 进行许多次局部运行以观察病理行为模式(例如,我们注意到,无论工作人员的数量和所评​​估的DL的大小如何,只有五个工作人员都在忙碌)