Dask图执行和内存使用

时间:2017-06-06 23:38:13

标签: python dask dask-delayed

我在dask中构建一个非常大的DAG以提交给分布式调度程序,其中节点在数据帧上运行,这些数据帧本身可能非常大。一种模式是我有大约50-60个函数来加载数据并构造每个几百MB的pandas数据帧(并且逻辑上代表单个表的分区)。我想将这些连接到图中下游节点的单个dask数据帧中,同时最小化数据移动。我将这样的任务链接起来:

dfs = [dask.delayed(load_pandas)(i) for i in disjoint_set_of_dfs]
dfs = [dask.delayed(pandas_to_dask)(df) for df in dfs]
return dask.delayed(concat_all)(dfs)

其中

def pandas_to_dask(df):
    return dask.dataframe.from_pandas(df).to_delayed()

我尝试了各种concat_all实施,但这似乎是合理的:

def concat_all(dfs):
    dfs = [dask.dataframe.from_delayed(df) for df in dfs]
    return dask.dataframe.multi.concat(dfs, axis='index', join='inner')

所有pandas数据帧的索引都是不相交的,并且是有序的/单调的。

然而,我正在被杀死的工作人员死于这个concat_all功能(集群管理器因为超出他们的内存预算而杀死他们),即使每个人的内存预算实际上相当大,我也不希望它移动数据。我有理由相信,在使用dask数据帧的graph nodse中调用compute()之前,我总是会切换到合理的数据子集。

到目前为止,我正在使用--memory-limit但没有成功。我至少正确地解决了这个问题吗?我缺少考虑因素吗?

1 个答案:

答案 0 :(得分:2)

给出计算到pandas数据帧的延迟值列表

>>> dfs = [dask.delayed(load_pandas)(i) for i in disjoint_set_of_dfs]
>>> type(dfs[0].compute())  # just checking that this is true
pandas.DataFrame

将它们传递给dask.dataframe.from_delayed功能

>>> ddf = dd.from_delayed(dfs)

默认情况下,这将运行第一个计算以确定元数据(对dask.dataframe很重要的列名,dtypes等)。您可以通过构建示例数据框并将其传递给meta=关键字来避免这种情况。

>>> meta = pd.DataFrame({'value': [1.0], 'name': ['foo'], 'id': [0]})
>>> ddf = dd.from_delayed(dfs, meta=meta)

example notebook也可能有所帮助。

通常,您永远不需要从其他dask函数中调用dask函数(就像您通过延迟from_pandas调用一样)。 Dask.dataframe函数本身已经很懒,不需要进一步延迟。