我正在使用 dask 延迟函数,并且熟悉@dask.delayed
在函数上使用装饰器时的注意事项。我意识到有时我需要调用compute()
两次才能获得结果,尽管我认为我遵循了最佳实践。即不要在另一个延迟延迟函数中调用延迟延迟函数。
我在两种情况下遇到了这个问题:当有嵌套函数时,以及在使用延迟对象的类成员的类中调用成员函数时。
@dask.delayed
def add(a, b):
return a + b
def inc(a):
return add(a, 1)
@dask.delayed
def foo(x):
return inc(x)
x = foo(3)
x.compute()
class Add():
def __init__(self, a, b):
self.a = a
self.b = b
@dask.delayed
def calc(self):
return self.a+self.b
a = dask.delayed(1)
b = dask.delayed(2)
add = Add(a, b)
add.calc().compute()
在第一个示例中,x.compute()
不返回结果而是另一个延迟对象,我将不得不调用x.compute().compute()
以获取实际结果。但我相信 inc 不是延迟函数,因此它不违反不在另一个延迟函数中调用延迟函数的规则?
在第二个示例中,我将不得不再次调用add.calc().compute().compute()
以获得实际结果。在这种情况下self.a
,andself.b
只是延迟属性,并且在任何地方都没有嵌套的延迟函数。
谁能帮我理解为什么compute()
在这两种情况下我需要打两次电话?或者更好的是,有人可以在使用 dask 延迟函数时简要解释一般“规则”吗?我阅读了文档,在那里找不到太多内容。
更新:@malbert 指出这些示例需要调用compute()
两次,因为延迟函数涉及延迟结果,因此它算作“在另一个延迟函数中调用延迟函数”。但是为什么像下面这样的事情只需要调用compute()
一次呢?
@dask.delayed
def add(a,b):
return a+b
a = dask.delayed(1)
b = dask.delayed(2)
c = add(a,b)
c.compute()
在这个例子中,a
和b
也是延迟的结果,它们用于延迟函数。我的随机猜测实际上重要的是延迟结果在延迟函数中的位置?只有当它们作为参数传入时才可能很好?