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
来说非常特殊。您认为这是否也适用于使用多处理
?再次感谢!