多处理池方法的性能问题

时间:2019-09-12 11:21:08

标签: python multiprocessing python-multiprocessing

我在数据框中有一个由项目列表组成的列,我想根据Fisher精确检验来计算该数据帧中的行(在本例中为列表)与所有其他行的相似度。为此,我想使用python多处理中的 Pool ,但这似乎要花费大约。与传统方法相同的时间(即使用嵌套的for循环)。有什么方法可以优化代码?

Fisher测试

def fisher_test(a, b, c, d):
    # do some stuff and return p value

使用嵌套的for循环进行计算:

%%time
import multiprocessing as mp
pool = mp.Pool(mp.cpu_count())


universeSize = 13000
# gq_result_df is a data frame
for i, row in gq_result_df.iterrows():
    for j in range(i, gq_result_df.shape[0]):
        if(i==j):
            continue
        pval = fisher_test(row["module_genes"], gq_result_df.loc[j,"module_genes"], universeSize)
        # pval_matrix is a matrix in which we are storing the result
        pval_matrix[i,j] = pval

使用Pool并行化内部循环:

%%time

universeSize = 13000

import multiprocessing as mp
pool = mp.Pool(mp.cpu_count())

for i, row in range(0, gq_result_df.shape[0]):

    pval = [pool.apply(fisher_test, args = (row["module_genes"], 
                                                         gq_result_df.loc[j,"module_genes"], universeSize)) for j in range(i+1, gq_result_df.shape[0])]
    #print("pval:", pval)
    for j in range(i +1, fish_pval_mat.shape[0]):
        pval_matrix[i, j] = pval[j -i -1]

pool.close()
pool.join()

我运行119次外循环的计算时间

  1. 不进行并行化:13分钟
  2. 使用并行化(使用Pool):12分钟

如何优化并行化代码以减少时间?在此先感谢

1 个答案:

答案 0 :(得分:2)

您的问题是使用Pool.apply(),因为它是阻塞呼叫。因此,您的执行不是并行的而是顺序的。 Pool.apply()阻塞直到有结果可用为止,这使其成为您提到的嵌套循环的另一种实现。您将一个块提交给子流程,等待其处理,然后再提交另一个-而不是一次全部提交。

我对这种特定算法不熟悉,不确定是否可以并行化-即是要独立处理的块,还是先前块的结果会影响连续的任务,在这种情况下不会并行化。

如果确实可以并行化,则可以尝试使用apply_async()。如果执行此操作,则界面将发生变化,因为您的pval不再是结果列表,而是AsyncResult对象的列表,并且您需要遍历这些对象和get()您的工人的实际结果。