Python 达斯克:为什么内存使用量激增?

Python 达斯克:为什么内存使用量激增?,python,pandas,data-science,dask,Python,Pandas,Data Science,Dask,我有一个小数据帧(大约100MB)和一个昂贵的计算,我想为每一行执行。它不是一个可矢量化的计算;它需要对每一行进行一些解析和DB查找 因此,我决定尝试Dask来并行化任务。任务是“令人尴尬的并行”,执行顺序或重复执行没有问题。然而,由于一些未知的原因,内存使用率高达约100GB 下面是有问题的代码示例: 将熊猫作为pd导入 将numpy作为np导入 将dask.dataframe作为dd导入 从dask.distributed导入客户端 从dask_作业队列导入LSFCluster cluste

我有一个小数据帧(大约100MB)和一个昂贵的计算,我想为每一行执行。它不是一个可矢量化的计算;它需要对每一行进行一些解析和DB查找

因此,我决定尝试Dask来并行化任务。任务是“令人尴尬的并行”,执行顺序或重复执行没有问题。然而,由于一些未知的原因,内存使用率高达约100GB

下面是有问题的代码示例:

将熊猫作为pd导入
将numpy作为np导入
将dask.dataframe作为dd导入
从dask.distributed导入客户端
从dask_作业队列导入LSFCluster
cluster=LSFCluster(memory=“6GB”,cores=1,project='gRNA Library Design')
集群规模(作业=16)
客户端=客户端(群集)
所需的目录=加载大目录()
得分指南=lambda行:昂贵的计算(必填项,行)
库\u df=pd.read\u csv(args.library\u csv)
meta=库类型
meta=meta.append(pd.Series({
“特异性”:np.dtype('int64'),
“切割效率”:np.dtype('int64'),
“0偏离目标”:np.dtype('object'),
“1偏离目标”:np.dtype('object'),
“2个偏离目标”:np.dtype('object'),
“3个偏离目标”:np.dtype('object'))
库\u ddf=dd.from\u熊猫(库\u df,npartitions=32)
库ddf=库ddf.apply(得分指南,轴=1,元=meta)
library\u ddf=library\u ddf.compute()
library\u ddf=library\u ddf.drop\u duplicates()
库到csv(args.outfile,index=False)
我的猜测是,查找所需的大字典是个问题,但它的大小总共只有~1.5GB,并且不包括在结果数据帧中


为什么Dask可能会占用大量内存?

不能100%确定在这种情况下这会解决问题,但您可以尝试对字典进行
futurize

#广播确保每个员工都有一份副本
[fut_dict]=客户端分散([required_dict],broadcast=True)
得分指南=lambda行:昂贵的计算(未来,行)
这样做的目的是将dict的副本放在每个worker上,并将对对象的引用存储在
fut_dict
中,从而避免了每次调用函数时都需要使用大型dict:

每次您传递一个具体的结果(任何没有延迟的结果)时,Dask都会在默认情况下对其进行散列,为其命名。这相当快(大约500 MB/s),但如果反复这样做,可能会很慢。相反,最好也延迟数据


请注意,这将消耗每个工作线程的一部分内存(例如,根据您的信息,每个工作线程将为dict分配1.5GB)。您可以在此阅读更多内容。

问题是需要序列化所需的
目录,并将其发送到所有工作线程。由于
required\u dict
很大,而且许多工作人员同时需要它,重复序列化会导致大量内存膨胀

有很多修复方法;对我来说,简单地从工作线程加载字典并显式地使用
map\u分区
而不是
apply
是最容易的

这是代码中的解决方案

def do_df(df):
所需的目录=加载大目录()
得分指南=lambda行:昂贵的计算(必填项,行)
返回df.apply(得分指南,轴=1)
库\u ddf=dd.from\u熊猫(库\u df,npartitions=128)
library\u ddf=library\u ddf.map\u分区(do\u df)
library\u ddf=library\u ddf.compute()

我尝试了类似的方法,但没有成功(可能是我的错误)。您已经正确地识别了问题:大字典是一个全局变量。由于有一个截止日期,我实现了一个更简单的解决方案。我将更新我的解决方案,并在明天研究其他解决方案。谢谢你的帮助。几周前我遇到了一个类似的问题。不知何故,将数据用作全局变量会使调度程序工作程序而不是单个工作程序过载。e、 在某个时候,我在类的构造函数中加载数据,这是一个非常糟糕的主意:)你应该朝那个方向看