合并字典时,Dask延迟对象的长度不确定,不会产生迭代错误

bla*_*lah 5 python dictionary dask dask-delayed

我正在尝试使用dask并行构建字典,但是遇到了TypeError: Delayed objects of unspecified length are not iterable

我正在尝试计算addsubtract并且multiply同时使字典的构建速度更快。

这是代表我的用例的一些代码:

import dask
from dask.delayed import delayed

x1 = {'a': 1, 'b': 2, 'c': 3}
x2 = {'a': 4, 'b': 5, 'c': 6}

@delayed
def add(d1, d2):
    z = {}
    z['func1_a'] = d1['a'] + d2['a']
    z['func1_b'] = d1['b'] + d2['b']
    z['func1_c'] = d1['c'] + d2['c']
    return z

@delayed
def subtract(d1, d2):
    z = {}
    z['func2_a'] = d1['a'] - d2['a']
    z['func2_b'] = d1['b'] - d2['b']
    z['func2_c'] = d1['c'] - d2['c']
    return z

@delayed
def multiply(d1, d2):
    z = {}
    z['func3_a'] = d1['a'] * d2['a']
    z['func3_b'] = d1['b'] * d2['b']
    z['func3_c'] = d1['c'] * d2['c']
    return z

@delayed
def last_step(d1, d2):
    z = {}
    z.update(add(d1, d2))
    z.update(subtract(d1, d2))
    z.update(multiply(d1, d2))
    return z
Run Code Online (Sandbox Code Playgroud)

最后,当我运行时:

>>> dask.compute(last_step(x1, x2))

<ipython-input-6-1153797c9d18> in final(d1, d2)
      2 def last_step(d1, d2):
      3     z = {}
----> 4     z.update(add(d1, d2))
      5     z.update(subtract(d1, d2))
      6     z.update(multiply(d1, d2))

/Users/me/anaconda3/lib/python3.6/site-packages/dask/delayed.py in __iter__(self)
    409     def __iter__(self):
    410         if getattr(self, '_length', None) is None:
--> 411             raise TypeError("Delayed objects of unspecified length are "
    412                             "not iterable")
    413         for i in range(self._length):

TypeError: Delayed objects of unspecified length are not iterable
Run Code Online (Sandbox Code Playgroud)

我在这里做错了/无法理解?

MRo*_*lin 5

您的z对象是一个字典,而结果add是一个 Delayed 对象。update 方法需要一个字典。Python 没有办法知道如何用一个对象更新一个字典,当你调用计算时,它会变成一个字典。

在这种情况下,我建议制作z成延迟对象

# z = {}
z = delayed({})
Run Code Online (Sandbox Code Playgroud)

z 将不再是一个 dict,它将成为一个将成为一个 dict 的东西。这意味着您不能再检查键、使用 getitem 语法插入其中、执行任何可变操作(如.update等),但仍然可以对其调用延迟方法。在您的情况下,我可能会使用纯函数,例如toolz.merge

只是为了设定期望。Dask.delayed 不会并行化完全任意的 Python 代码。您仍然需要做一些工作来考虑对象何时延迟以及什么是具体的。