Python 多处理池方法的性能问题

Python 多处理池方法的性能问题,python,multiprocessing,python-multiprocessing,Python,Multiprocessing,Python Multiprocessing,我在一个数据框中有一列,它由一个项目列表组成,我想根据Fisher精确测试计算该数据框的行(在本例中为列表)与所有其他行的相似性。为此,我想使用python multiprocessing中的Pool,但它似乎占用了与传统方法差不多的时间(即使用嵌套For循环)。有什么方法可以优化代码吗 费希尔试验 def fisher_test(a, b, c, d): # do some stuff and return p value 使用嵌套for循环进行计算: %%time import m

我在一个数据框中有一列,它由一个项目列表组成,我想根据Fisher精确测试计算该数据框的行(在本例中为列表)与所有其他行的相似性。为此,我想使用python multiprocessing中的Pool,但它似乎占用了与传统方法差不多的时间(即使用嵌套For循环)。有什么方法可以优化代码吗

费希尔试验

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

使用池并行化内部循环:

%%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次时的计算时间

  • 未并行化:13分钟
  • 并行化(使用池):12分钟

  • 如何优化并行化代码以减少时间?提前感谢

    您的问题是使用了
    Pool.apply()
    ,因为这是一个阻塞调用。因此,您的执行不是并行的,而是顺序的。Pool.apply()阻塞,直到结果可用,这只是您提到的嵌套循环的另一个实现。您将一个区块提交给子流程,等待它被处理,然后再提交另一个区块,而不是一次提交所有区块

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


    如果它确实并行化,您可以尝试使用
    apply\u async()
    。如果您这样做,那么界面会发生一些变化,因为您的
    pval
    不再是一个结果列表,而是一个
    AsyncResult
    对象列表,您需要遍历这些对象并
    get()
    从您的工作人员那里获得实际结果。

    fisher_test来自哪里?是您自己定义的,还是导入的?我自己定义的@Jamesyes,
    apply\u async()
    可以正常工作。但是,
    apply_async()
    的一个警告是,结果中的数字顺序混乱,表明进程没有按照启动顺序完成。不,它不能保证-这或多或少是并行处理的重点。如果您对顺序感兴趣,可以将索引作为apply_async中的参数发送给工作人员,然后在结果集中返回未修改的索引。在这种情况下,更简单的是,pval列表的形成顺序就是提交顺序。如果您在for循环中枚举该值以获得结果,那么如果足够的话,您至少可以免费获得序号。