Python 为什么在大熊猫中,多处理比简单计算慢?

Python 为什么在大熊猫中,多处理比简单计算慢?,python,pandas,multiprocessing,python-multiprocessing,dask,Python,Pandas,Multiprocessing,Python Multiprocessing,Dask,这与 再考虑一下这个简单(但有趣)的例子: import dask.dataframe as dd import dask.multiprocessing import dask.threaded from fuzzywuzzy import fuzz import pandas as pd master= pd.DataFrame({'original':['this is a nice sentence', 'this is another one', 'stackoverflow is

这与

再考虑一下这个简单(但有趣)的例子:

import dask.dataframe as dd
import dask.multiprocessing
import dask.threaded
from fuzzywuzzy import fuzz
import pandas as pd

master= pd.DataFrame({'original':['this is a nice sentence',
'this is another one',
'stackoverflow is nice']})

slave= pd.DataFrame({'name':['hello world',
'congratulations',
'this is a nice sentence ',
'this is another one',
'stackoverflow is nice'],'my_value': [1,2,3,4,5]})

def fuzzy_score(str1, str2):
    return fuzz.token_set_ratio(str1, str2)

def helper(orig_string, slave_df):
    slave_df['score'] = slave_df.name.apply(lambda x: fuzzy_score(x,orig_string))
    #return my_value corresponding to the highest score
    return slave_df.loc[slave_df.score.idxmax(),'my_value']

master
Out[39]: 
                  original
0  this is a nice sentence
1      this is another one
2    stackoverflow is nice

slave
Out[40]: 
   my_value                      name
0         1               hello world
1         2           congratulations
2         3  this is a nice sentence 
3         4       this is another one
4         5     stackoverflow is nice
我需要做的很简单:

  • 对于
    master
    中的每一行,我使用
    fuzzyfuzzy
    计算的字符串相似性分数查找数据帧
    slave
    ,以获得最佳匹配
现在让我们将这些数据帧放大一点:

master = pd.concat([master] * 100,  ignore_index  = True)
slave = pd.concat([slave] * 10,  ignore_index  = True)
首先,我尝试了
dask

#prepare the computation
dmaster = dd.from_pandas(master, npartitions=4)
dmaster['my_value'] = dmaster.original.apply(lambda x: helper(x, slave),meta=('x','f8'))
下面是时间安排:

#multithreaded
%timeit dmaster.compute(get=dask.threaded.get) 
1 loop, best of 3: 346 ms per loop

#multiprocess
%timeit dmaster.compute(get=dask.multiprocessing.get) 
1 loop, best of 3: 1.93 s per loop

#good 'ol pandas
%timeit master['my_value'] = master.original.apply(lambda x: helper(x,slave))
100 loops, best of 3: 2.18 ms per loop
第二,我尝试了好的
多处理

from multiprocessing import Pool, cpu_count

def myfunc(df):
    return df.original.apply(lambda x: helper(x, slave))

from datetime import datetime

if __name__ == '__main__':
     startTime = datetime.now()
     p = Pool(cpu_count() - 1)
     ret_list = p.map(myfunc, [master.iloc[1:100,], master.iloc[100:200 ,],
                               master.iloc[200:300 ,]])
     results = pd.concat(ret_list)
     print datetime.now() - startTime
它给出了大约相同的时间

runfile('C:/Users/john/untitled6.py', wdir='C:/Users/john')
0:00:01.927000
问题:为什么使用
Dask
多处理
的多处理与这里的熊猫相比如此缓慢?假设我的真实数据比这个大得多。我能得到更好的结果吗

毕竟,我考虑的问题是<>代码>并行的(每行都是独立的问题),所以这些包应该真的闪亮。p> 我是不是遗漏了什么


谢谢

让我把我的评论总结成一个答案。我希望这些信息证明是有用的,因为这里有很多问题

首先,我想向您介绍distributed.readthedocs.io/en/latest/efficiency.html,其中讨论了许多dask性能主题。请注意,这是分布式调度器的全部功能,但由于它可以在进程内启动,可以使用线程或进程,或者这些线程或进程的组合,因此它确实取代了以前的dask调度器,并且通常在所有情况下都推荐使用

1) 创建流程需要时间。这总是正确的,尤其是在windows上。如果您对现实生活中的性能感兴趣,那么您将只需要创建一次流程,其开销是固定的,并运行许多任务。在dask中,即使是在本地,也有许多创建集群的方法


2) dask(或任何其他调度程序)处理的每个任务都会产生一些开销。在分布式调度器的情况下,我假设这是因为您需要更多的计算(水平扩展)能力来证明dask具有的所有额外开销。这还不够!numpy也能做到这一点,您将需要更多的计算机:在开始计算任何东西之前,对多处理的第一次调用将需要时间来加速额外的进程。如果您的所有数据都能很好地存储在内存中,dask不一定是正确的选择。哦,你应该使用分布式调度器,甚至在一台机器上。接下来,你需要考虑任务的速度(2MS/4块,即非常快),与串行化数据所需的时间相比,将数据发送到进程,反序列化数据,并返回输出。此外还有管理任务执行的开销。这些听起来像是答案吗?在非常好的会议上进行一些讨论。有一件事你可以尝试让你的问题更具信息性,那就是找到这样一个门槛。也就是说,您是否可以尝试使用足够大的数据帧在您的计算机上运行我的代码,以便dask或多处理更快?如果没有你的数据,那就太不可思议了:|此外,“阈值”将取决于大量变量,因此最好遵守这里描述的经验法则。没有,但我是指上面的工作示例。您可以改变示例DataFrame的大小,请参见上面的3),您不应该在一个进程中创建数据并将其传递给工作人员,在这种情况下,序列化/通信需要比处理更长的时间,您永远不会赢。我明白了,真的谢谢。但这对于
dask
来说非常特殊。您认为这是否也适用于使用
多处理
?再次感谢!