我想在Python中使用df.corr()
模块并行化multiprocessing
。我正在使用一列并计算相关值,其中一个进程和第二列中的所有列都处于休息状态,其他进程中的其他列则处于休息状态。我继续以这种方式通过堆叠来自所有过程的结果行来填充相关矩阵的上层。
我获取了形状(678461, 210)
的示例数据并尝试了我的并行化方法和df.corr()
,并分别获得214.40s
和42.64s
的运行时间。所以,我的并行化方法需要更多时间。
有没有办法改善这个?
import multiprocessing as mp
import pandas as pd
import numpy as np
from time import *
def _correlation(args):
i, mat, mask = args
ac = mat[i]
arr = []
for j in range(len(mat)):
if i > j:
continue
bc = mat[j]
valid = mask[i] & mask[j]
if valid.sum() < 1:
c = NA
elif i == j:
c = 1.
elif not valid.all():
c = np.corrcoef(ac[valid], bc[valid])[0, 1]
else:
c = np.corrcoef(ac, bc)[0, 1]
arr.append((j, c))
return arr
def correlation_multi(df):
numeric_df = df._get_numeric_data()
cols = numeric_df.columns
mat = numeric_df.values
mat = pd.core.common._ensure_float64(mat).T
K = len(cols)
correl = np.empty((K, K), dtype=float)
mask = np.isfinite(mat)
pool = mp.Pool(processes=4)
ret_list = pool.map(_correlation, [(i, mat, mask) for i in range(len(mat))])
for i, arr in enumerate(ret_list):
for l in arr:
j = l[0]
c = l[1]
correl[i, j] = c
correl[j, i] = c
return pd.DataFrame(correl, index = cols, columns = cols)
if __name__ == '__main__':
noise = pd.DataFrame(np.random.randint(0,100,size=(100000, 50)))
noise2 = pd.DataFrame(np.random.randint(100,200,size=(100000, 50)))
df = pd.concat([noise, noise2], axis=1)
#Single process correlation
start = time()
s = df.corr()
print('Time taken: ',time()-start)
#Multi process correlation
start = time()
s1 = correlation_multi(df)
print('Time taken: ',time()-start)
答案 0 :(得分:0)
_correlation
的结果必须通过进程间通信从工作进程移动到运行Pool
的进程。
这意味着返回数据被pickle,发送到其他进程,unpickled并添加到结果列表中。 这需要时间,本质上是一个连续的过程。
map
按照发送顺序处理退货,IIRC。因此,如果一次迭代需要相对较长的时间,其他结果可能会停滞等待。您可以尝试使用imap_unordered
,一旦到达就会产生结果。