报告Dask任务的进度

时间:2019-12-24 11:27:12

标签: python parallel-processing distributed-computing dask dask-distributed

我正在Dask调度程序上运行许多缓慢的任务,并且我希望每个任务都有进度报告。这些任务将从处理进度报告的同一台计算机上提交,因此可以保留在同一流程中,但是现在让我们仅假设任务已提交且进度报告在单独的流程中进行处理。

Dask提供了Coordination Primitives,其预期用例包括能够监视进度:

  

这些可用于控制对外部资源的访问,跟踪正在进行的计算的进度,或在许多工作人员,客户端和任务之间的副渠道中共享数据。

我能想到的最简单的示例如下:

任务提交者:

from dask.distributed import Client, Pub
import time

c = Client('tcp://127.0.0.1:8786')

def slow_func():
    q = Pub('progress')
    for i in range(10):
        q.put(f'{i}/10')
        time.sleep(1)

c.submit(slow_func)

任务报告者:

from dask.distributed import Client, Sub

c = Client('tcp://127.0.0.1:8786')
q = Sub('progress')
while True:
    print(q.get())

这可以与Pub / Sub一起使用,但也可以与Queue一起使用。现在,即使它确实起作用了,但这似乎也不是作者的初衷:

  • 我最终隐含地依赖于我在执行报告时提交任务所使用的Client;即Client最终出现在工作节点上。这感觉很奇怪。
  • 我无法区分不同的任务;理想情况下,我可以在报告中使用诸如未来之钥之类的东西。

因此,我承认的一个模糊的问题是:就创建Dask未来提供进度报告的“ Hello world”风格示例而言,我如何将上述内容修改为可以被视为惯用的Dask,并且在那里有什么陷阱要注意吗?

我可以通过为每个任务创建一个新的客户端来部分解决我的第一个问题(下面的示例),但是由于我最终得到的东西看起来可以正常工作,因此这样做是不必要的。

import time
from dask.distributed import Client, Pub

c_submit = Client('tcp://127.0.0.1:8786')

def slow_func():
    c_report = Client('tcp://127.0.0.1:8786')
    q = Pub('progress', client=c_report)
    for i in range(10):
        q.put(f'{i}/10')
        time.sleep(1)

c_submit.submit(slow_func)

1 个答案:

答案 0 :(得分:1)

问题dask.distributed.worker_client的存在可以回答问题的第一部分,该问题正是我们所需要的:提供一个与当前工作程序的调度程序对话的客户。这样,任务提交者将变为:

import time
from dask.distributed import Client, Pub, worker_client

c_submit = Client('tcp://127.0.0.1:8786')

def slow_func():
    with worker_client() as c_report:
        q = Pub('progress', client=c_report)
        for i in range(10):
            q.put(f'{i}/10')
            time.sleep(1)
c_submit.submit(slow_func)

对于第二部分,一种不可怕的方法是在每次提交任务时简单地生成一个ID。也就是说,执行以下操作:

import time
import uuid

from dask.distributed import Client, Pub, worker_client

c_submit = Client('tcp://127.0.0.1:8786')

def slow_func(task_id):
    with worker_client() as c_report:
        q = Pub('progress', client=c_report)
        for i in range(10):
            q.put(f'{task_id}: {i}/10')
            time.sleep(1)

c_submit.submit(slow_func, uuid.uuid4())

这可以解决我的问题,但是当未来的密钥中已经有一个可以完美使用的ID时,使用新ID仍然感到有些奇怪。