Я работаю с отложенными функциями dask и знакомлюсь с тем, что можно и чего нельзя делать при использовании декоратора @dask.delayed
для функций. Я понял, что иногда мне нужно дважды позвонить compute()
, чтобы получить результат, несмотря на то, что я думал, что следую лучшим практикам. т.е. не вызывать отложенную функцию dask внутри другой отложенной функции dask.
Я столкнулся с этой проблемой в двух сценариях: при наличии вложенных функций и при вызове функции-члена в классе, использующем члены класса, являющиеся отложенными объектами.
@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
и self.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
также являются отложенными результатами, и они используются в отложенной функции. Моя случайная догадка заключается в том, что на самом деле имеет значение, где задержанный результат находится в отложенной функции? Возможно, это нормально, только если они будут переданы в качестве аргументов?