[英]Why does joblib.Parallel() take much more time than a non-paralleled computation? Shouldn't Parallel() run faster than a non-paralleled computation?
[英]Why is pandas.grouby.mean so much faster than paralleled implementation
我在一个非常大的数据集上使用如下所示的 pandas grouby mean 函数:
import pandas as pd
df=pd.read_csv("large_dataset.csv")
df.groupby(['variable']).mean()
看起来该函数没有使用多处理,因此,我实现了一个并行版本:
import pandas as pd
from multiprocessing import Pool, cpu_count
def meanFunc(tmp_name, df_input):
df_res=df_input.mean().to_frame().transpose()
return df_res
def applyParallel(dfGrouped, func):
num_process=int(cpu_count())
with Pool(num_process) as p:
ret_list=p.starmap(func, [[name, group] for name, group in dfGrouped])
return pd.concat(ret_list)
applyParallel(df.groupby(['variable']), meanFunc)
然而,似乎大熊猫实施仍远低于我的并行实现更快。
我正在查看 pandas groupby 的源代码,我看到它正在使用 cython。 是这个原因吗?
def _cython_agg_general(self, how, alt=None, numeric_only=True,
min_count=-1):
output = {}
for name, obj in self._iterate_slices():
is_numeric = is_numeric_dtype(obj.dtype)
if numeric_only and not is_numeric:
continue
try:
result, names = self.grouper.aggregate(obj.values, how,
min_count=min_count)
except AssertionError as e:
raise GroupByError(str(e))
output[name] = self._try_cast(result, obj)
if len(output) == 0:
raise DataError('No numeric types to aggregate')
return self._wrap_aggregated_output(output, names)
简短回答 - 如果您想要这些类型的情况的并行性,请使用dask 。 你在你的方法中有它避免的陷阱。 它仍然可能不会更快,但会给你最好的镜头,并且在很大程度上是熊猫的替代品。
更长的答案
1) 并行性本质上会增加开销,因此理想情况下,您并行的操作有些昂贵。 添加数字并不是特别的 - 在这里使用 cython 是对的,您正在查看的代码是调度逻辑。 实际的核心 cython 在这里,它转化为一个非常简单的 c 循环。
2)您正在使用多处理 - 这意味着每个进程都需要获取数据的副本。 这是昂贵的。 通常,由于 GIL,您必须在 python 中执行此操作 - 您实际上可以(并且 dask 确实)在这里使用线程,因为 Pandas 操作在 C 中并释放 GIL。
3)正如@AKX 在评论中指出的那样 - 并行化之前的迭代( ... name, group in dfGrouped
)也相对昂贵 - 它为每个组构建新的子数据帧。 原始的 Pandas 算法在原地迭代数据。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.