自定义图中的Dask机会缓存

自定义图中的Dask机会缓存,dask,Dask,我有一个自定义DAG,例如: dag = {'load': (load, 'myfile.txt'), 'heavy_comp': (heavy_comp, 'load'), 'simple_comp_1': (sc_1, 'heavy_comp'), 'simple_comp_2': (sc_2, 'heavy_comp'), 'simple_comp_3': (sc_3, 'heavy_comp')} 我希望计算键simple\u c

我有一个自定义DAG,例如:

dag = {'load': (load, 'myfile.txt'),
       'heavy_comp': (heavy_comp, 'load'),
       'simple_comp_1': (sc_1, 'heavy_comp'),
       'simple_comp_2': (sc_2, 'heavy_comp'),
       'simple_comp_3': (sc_3, 'heavy_comp')}
我希望计算键
simple\u comp\u 1
simple\u comp\u 2
,和
simple\u comp\u 3
,我执行如下操作

import dask
from dask.distributed import Client
from dask_yarn import YarnCluster

task_1 = dask.get(dag, 'simple_comp_1')
task_2 = dask.get(dag, 'simple_comp_2')
task_3 = dask.get(dag, 'simple_comp_3')
tasks = [task_1, task_2, task_3]

cluster = YarnCluster()
cluster.scale(3)
client = Client(cluster)
dask.compute(tasks)
cluster.shutdown()
在没有缓存的情况下,这3个键的计算似乎也会导致计算
heavy\u comp
3次。由于这是一个繁重的计算,我尝试从以下方面实现机会主义缓存:

from dask.cache import Cache
cache = Cache(2e9)
cache.register()
但是,当我试图打印缓存内容的结果时,却一无所获:

>>> cache.cache.data
[]
>>> cache.cache.heap.heap
{}
>>> cache.cache.nbytes
{}

我甚至尝试将缓存大小增加到6GB,但是没有效果。我做错什么了吗?如何让Dask缓存密钥的结果?

核心Dask库中的机会缓存仅适用于单机调度器,而不适用于分布式调度器


但是,如果您一次计算整个图形,Dask将智能地保留中间值。如果有您希望保留的值,您也可以查看
persist
函数。

扩展MRocklin的答案,并在问题下方的注释中格式化代码

一次计算整个图形的效果与您预期的一样
heavy_comp
只执行一次,这是您想要的。考虑在空函数定义完成的注释中提供的以下代码:

def load(fn):
    print('load')
    return fn

def sc_1(i):
    print('sc_1')
    return i

def sc_2(i):
    print('sc_2')
    return i

def sc_3(i):
    print('sc_3')
    return i

def heavy_comp(i):
    print('heavy_comp')
    return i

def merge(*args):
    print('merge')
    return args

dag = {'load': (load, 'myfile.txt'), 'heavy_comp': (heavy_comp, 'load'), 'simple_comp_1': (sc_1, 'heavy_comp'), 'simple_comp_2': (sc_2, 'heavy_comp'), 'simple_comp_3': (sc_3, 'heavy_comp'), 'merger_comp': (merge, 'sc_1', 'sc_2', 'sc_3')}

import dask
result = dask.get(dag, 'merger_comp')
print('result:', result)
它输出:


如您所见,“heavy_comp”仅打印一次,表明函数
heavy_comp
仅执行过一次。

如何评估图形?原则上,如果您使用类似于
dask.get(dag,[simple\u comp1,simple\u comp2,simple\u comp3])的方法计算密钥,则只能计算一次
heavy\u comp
@malbert,很抱歉,我应该添加有关如何评估图表的详细信息,我现在对上述问题进行了编辑。键
heavy_comp
load
的计算是否只会以我上面所示的方式进行一次,还是必须像您所示的那样将键格式化为列表?如果没有缓存,每次调用
dask.get
,所有必要的计算都将从头开始执行。实际上,缓存应该注意存储中间结果,例如
heavy\u comp
。不幸的是,我没有使用内置缓存的经验。但是,您的问题可以通过调用
dask.get(dag[simple\u comp1,simple\u comp2,simple\u comp3])
来解决(正如您所说,关键字以列表的形式给出),因为
heavy\u comp
只会被禁用一次。还有一件事:在你的例子中,你应该只调用
dask.get
而不是
get
,然后
compute
@malbert,那么你是说
dask.get(dag,simple\u comp1,simple\u comp2,simple\u comp3])
将缓存,而执行
dask get(dag,simple\u compx)
3次则不会?你对此有多确定?你有推荐信吗?同样,不确定你使用“代码> DASK的意思。获得< <代码>而不是<代码>获取< /代码> -我不是上面所示的吗?关于如何确信,说服自己:考虑这个图<代码>导入时间;dag={'1':'heavy','2':'heavy','heavy':(time.sleep,1)}
[dask.get(dag,i)for i in['1','2']
需要两秒钟,而
dask.get(dag,['1','2'])
只需要一秒钟。如果我错了,请纠正我,但是
不会持久化
只适用于Numpy/dask数据结构,如数组/数据帧?谢谢@malbert,这已验证!
load
heavy_comp
sc_1
sc_2
sc_3
merge
result: ('sc_1', 'sc_2', 'sc_3')