繁体   English   中英

Dask 如何决定是否重新运行任务

[英]How does Dask decide whether to rerun a task or not

我对 Dask 很陌生,并试图构建一个系统来执行具有依赖关系的计算图。 但是,尽管某些任务具有 static 签名,但我对某些任务执行两次这一事实感到非常困惑。 例如:

Python 3.7.5 (default, Nov 12 2019, 11:34:05)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-18)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from dask.distributed import Client
>>> client = Client()
>>> def a():
...   print("a")
...
>>> client.gather(client.submit(a))
a
>>> client.gather(client.submit(a))
a
>>> client.submit(a)
<Future: pending, key: a-a5eb50e9015acdf60b1094aa4e467e00>
a
>>> client.submit(a)
<Future: finished, type: builtins.NoneType, key: a-a5eb50e9015acdf60b1094aa4e467e00>
>>> client.gather(client.submit(a))
>>> client.gather(client.submit(a))
>>>

所以看起来a()是使用client.gather(client.submit(a))为每个调用执行的,但只有在我自己调用client.submit(a)之前,相同的Future被重用并且 function不再被调用。 这是为什么?

在我的计算图中,当两个任务依赖于同一个任务时,这将是一个问题,该任务应该只执行一次。 我目前处理此类依赖项(递归)的方法如下:

from dask.distributed import Client, worker_client

def x(n):
    dgraph = {
        'a': [],
        'b': ['a'],
        'c': ['b', 'a'],
        'd': ['b', 'c']
        }
    print(n)
    with worker_client() as client:
        client.gather(list(client.submit(x, d) for d in dgraph[n]))

if __name__ == '__main__':
    client = Client()
    result = client.submit(x, 'd')
    client.gather(result)

有趣的是,python 的 output 在执行该脚本时并不稳定:

$ python test_dask2.py
d
b
c
a
b
a
a
$ python test_dask2.py
d
b
c
a
distributed.scheduler - CRITICAL - Tried writing to closed comm: {'op': 'lost-data', 'key': 'x-bff0c0d6e4239ae9c5beaed070018a1e'}
distributed.scheduler - CRITICAL - Tried writing to closed comm: {'op': 'lost-data', 'key': 'x-59dc11a9fc2db8a0885e47d3e5891304'}
$

有没有办法确保具有给定输入的给定任务即使我提交多次也只执行一次? 如果我正确理解文档,那应该是正常行为。 如果对print的调用是防止这种情况的副作用,为什么它不一致,我如何防止生成 output 文件的任务被执行两次?

另外,最后的错误是什么,并不总是发生?

编辑:

我想我明白了为什么我的一些任务在第二个片段中运行了多次:dask 的submit分配给任务以进行识别的 hash 值似乎有时会发生变化,即使在多次提交相同的任务时(甚至在任务之前)完成并超出范围)。 submit中将key参数设置为固定值(例如任务的名称)可以解决该问题。

简短的回答是:dask 在需要时将结果保留在 memory 中。 在这些情况下,“需要”可以是 session 中的未来,也可以是取决于结果的其他任务。

在像client.gather(client.submit(a))这样的行中,由submit生成的未来在收集后立即被遗忘。 在像client.submit(a)这样的行中,生成的未来存储在 session 的“最后结果”变量_中,因此仍然被记住并且集群不会清除它。

如果你想要更多的控制,你可以分配这些变量:

fut = client.submit(a)  # sets func running, keeps hold of the future
fut2 = client.submit(a)  # uses already existing task to get result
client.gather(fut), fut.result() # get results
del fut2, fut  #  "forget" futures, and have cluster release them

记得使用仪表板查看集群当前的 state。

我认为您正在寻找以下文档页面https://distributed.dask.org/en/latest/memory.html

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM