Python 2.7 如何在自定义dask图中调用Executor.map?

Python 2.7 如何在自定义dask图中调用Executor.map?,python-2.7,anaconda,distributed,distributed-computing,dask,Python 2.7,Anaconda,Distributed,Distributed Computing,Dask,我有一个计算,由3个“映射”步骤组成,最后一个步骤取决于前两个步骤的结果。我使用运行在多台PC上的分布式dask执行此任务 依赖关系图如下所示 map(func1, list1) -> res_list1-\ | -> create_list_3(res_list1, res_list2)-> list3 -> map(func3, list3) map(func2, list2) -> res_lis

我有一个计算,由3个“映射”步骤组成,最后一个步骤取决于前两个步骤的结果。我使用运行在多台PC上的分布式dask执行此任务

依赖关系图如下所示

map(func1, list1) -> res_list1-\
                                | -> create_list_3(res_list1, res_list2)-> list3 -> map(func3, list3)
map(func2, list2) -> res_list2-/
如果我们假设这些计算是独立的,那么调用
map
函数3次就很简单了

from distributed import Executor, progress

def process(jobid):
    e = Executor('{address}:{port}'.format(address=config('SERVER_ADDR'),
                                           port=config('SERVER_PORT')))
    futures = []
    futures.append(e.map(func1, list1))
    futures.append(e.map(func2, list2))
    futures.append(e.map(func3, list3))

    return futures

if __name__ == '__main__':
    jobid = 'blah-blah-blah'
    r = process(jobid)
    progress(r)
但是,
list3
是根据
func1
func2
的结果构建的,它的创建不容易
map
pab(
list1
list2
res_list1
res_list2
存储在Postgresql数据库中,创建
list3
是一个
JOIN
查询,需要一些时间)

我尝试将调用添加到期货列表中的
submit
,但是,这并没有像预期的那样起作用:

def process(jobid):
    e = Executor('{address}:{port}'.format(address=config('SERVER_ADDR'),
                                           port=config('SERVER_PORT')))
    futures = []
    futures.append(e.map(func1, list1))
    futures.append(e.map(func2, list2))
    futures.append(e.submit(create_list_3))
    futures.append(e.map(func3, list3))

    return futures
在这种情况下,一个
dask工作者
已收到要执行的任务
create_list_3
,但其他人同时收到要调用
func3
的任务,这些任务出现了错误,因为
list3
不存在

很明显,我缺少同步。工作人员必须停止并等待
list3
的创建完成

dask的
dask
文档描述了可以提供同步的自定义任务图

但是,文档中的示例不包括
map
函数,只包括简单的计算,如调用
add
inc


在我的例子中,是否可以使用
map
和自定义dask图,或者我是否应该实现与
dask
中未包含的其他方法的同步?

如果您希望链接任务之间的依赖关系,则应将以前任务的输出传递到另一个任务的输入

futures1 = e.map(func1, list1)
futures2 = e.map(func2, list2)
futures3 = e.map(func3, futures1, futures2)
对于
func3
Dask的任何调用,Dask将处理等待,直到输入准备就绪,并将从计算结果的任何位置向该函数发送适当的结果

但是,您似乎希望通过其他自定义方式处理数据传输和同步。如果是这样,那么将一些令牌传递给对
func3
的调用可能会很有用

futures1 = e.map(func1, list1)
futures2 = e.map(func2, list2)

def do_nothing(*args):
    return None

token1 = e.submit(do_nothing, futures1)
token2 = e.submit(do_nothing, futures2)

list3 = e.submit(create_list_3)

def func3(arg, tokens=None):
    ...

futures3 = e.map(func3, list3, tokens=[token1, token2])
这有点像黑客,但会迫使所有
func3
函数等待,直到它们能够从以前的map调用中获得令牌结果


但是,我建议尝试做第一个选项。这将使dask在运行时更加智能,并可以释放资源。像
token1/2
这样的障碍会导致次优调度。

发现了这个链接:Title很有希望。是的,我将实际结果存储在数据库中,函数返回token。