Python 为什么对熊猫使用多处理会导致如此显著的加速?

Python 为什么对熊猫使用多处理会导致如此显著的加速?,python,performance,pandas,dataframe,multiprocessing,Python,Performance,Pandas,Dataframe,Multiprocessing,假设我有一个数据帧和一个我想应用于每一行的函数。我可以调用df.apply(apply_fn,axis=1),它的时间应该是df大小的线性时间。或者我可以拆分df并使用pool.map在每个片段上调用我的函数,然后连接结果 我希望使用pool.map时的加速因子大致等于池中的进程数(如果使用N个处理器,则新的执行时间=原始执行时间/N,并且假设开销为零) 相反,在这个玩具示例中,当使用4个处理器时,时间下降到大约2%(0.005272/0.230757)。我最多只期望25%。发生了什么事?我不明

假设我有一个数据帧和一个我想应用于每一行的函数。我可以调用
df.apply(apply_fn,axis=1)
,它的时间应该是
df
大小的线性时间。或者我可以拆分
df
并使用
pool.map
在每个片段上调用我的函数,然后连接结果

我希望使用
pool.map
时的加速因子大致等于池中的进程数(如果使用N个处理器,则新的执行时间=原始执行时间/N,并且假设开销为零)

相反,在这个玩具示例中,当使用4个处理器时,时间下降到大约2%(0.005272/0.230757)。我最多只期望25%。发生了什么事?我不明白什么

import numpy as np
from multiprocessing import Pool
import pandas as pd
import pdb
import time

n = 1000
variables = {"hello":np.arange(n), "there":np.random.randn(n)}
df = pd.DataFrame(variables)

def apply_fn(series):
    return pd.Series({"col_5":5, "col_88":88,
                      "sum_hello_there":series["hello"] + series["there"]})

def call_apply_fn(df):
    return df.apply(apply_fn, axis=1)

n_processes = 4  # My machine has 4 CPUs
pool = Pool(processes=n_processes)

t0 = time.process_time()
new_df = df.apply(apply_fn, axis=1)
t1 = time.process_time()
df_split = np.array_split(df, n_processes)
pool_results = pool.map(call_apply_fn, df_split)
new_df2 = pd.concat(pool_results)
t2 = time.process_time()
new_df3 = df.apply(apply_fn, axis=1)  # Try df.apply a second time
t3 = time.process_time()

print("identical results: %s" % np.all(np.isclose(new_df, new_df2)))  # True
print("t1 - t0 = %f" % (t1 - t0))  # I got 0.230757
print("t2 - t1 = %f" % (t2 - t1))  # I got 0.005272
print("t3 - t2 = %f" % (t3 - t2))  # I got 0.229413
我保存了上面的代码,并使用python3 my_filename.py运行它

PS我意识到,在这个玩具示例中,
new_df
可以以更简单的方式创建,而无需使用apply。我感兴趣的是使用更复杂的
apply\fn
来应用类似的代码,而不仅仅是添加列。

Edit(我以前的答案实际上是错误的。)

time.process\u time()
()只测量当前进程中的时间(不包括睡眠时间)。因此,在子进程中花费的时间没有考虑在内


我使用
time.time()
运行您的代码,它测量真实世界的时间(根本没有显示加速),并且使用更可靠的
timeit.timeit
(大约50%的加速)。我有4个核。

谢谢,你一定是对的。不过,我不太明白发生了什么事。为什么即使
time.process\u time()
调用在多处理调用之外,也会发生这种情况?是因为
time.process\u time()
只返回父进程的CPU时间吗?@Adrian抱歉,我错了-子进程根本没有弄乱
process\u time
。很抱歉给你带来了困惑。我更新了答案。