大型Pandas数据框并行处理

14

我正在访问一个非常大的Pandas数据框作为全局变量。这个变量通过joblib并行访问。

例如。

df = db.query("select id, a_lot_of_data from table")

def process(id):
    temp_df = df.loc[id]
    temp_df.apply(another_function)

Parallel(n_jobs=8)(delayed(process)(id) for id in df['id'].to_list())

以这种方式访问原始df似乎会在进程之间复制数据。这是意外的,因为原始df在任何子进程中都没有被改变?(还是有改变吗?)

2个回答

13
整个 DataFrame 需要被 pickle 和 unpickle,以供 joblib 创建的每个进程使用。在实践中,这非常缓慢,还需要多次内存。一个解决方案是将数据存储在 HDF 中(df.to_hdf)使用表格式。然后可以使用 select 选择子集进行进一步处理。在实践中,这对交互式使用来说速度太慢了。它也非常复杂,您的工作人员将需要存储他们的工作,以便在最后一步中合并。另一个选择是探索带有 target='parallel'numba.vectorize。这将需要使用 NumPy 数组而不是 Pandas 对象,因此也有一些复杂成本。从长远来看,希望 dask 能够为 Pandas 带来并行执行,但这不是要期望的事情。

1
我曾经认为从https://dev59.com/KWgv5IYBdhLWcg3wSewe得到的结论是,除非修改了原始对象,否则子进程不会收到完整的副本。那么joblib是否能够保持写入时复制语义呢? - autodidacticon
1
只有少数类型可以使用共享内存传递。Pandas对象不在此列表中。joblib根据数组大小自动处理numpy数组的内存共享,使用关键字参数max_nbytes调用Parallel。请参见joblib网站。还可以参见此答案。当然,您可以使用NumPy数组代替Pandas,这可能会加快速度。 - Kevin S

3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接