我在数据框中有一个由项目列表组成的列,我想根据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次外循环的计算时间
如何优化并行化代码以减少时间?在此先感谢
答案 0 :(得分:2)
您的问题是使用Pool.apply()
,因为它是阻塞呼叫。因此,您的执行不是并行的而是顺序的。 Pool.apply()阻塞直到有结果可用为止,这使其成为您提到的嵌套循环的另一种实现。您将一个块提交给子流程,等待其处理,然后再提交另一个-而不是一次全部提交。
我对这种特定算法不熟悉,不确定是否可以并行化-即是要独立处理的块,还是先前块的结果会影响连续的任务,在这种情况下不会并行化。
如果确实可以并行化,则可以尝试使用apply_async()
。如果执行此操作,则界面将发生变化,因为您的pval
不再是结果列表,而是AsyncResult
对象的列表,并且您需要遍历这些对象和get()
您的工人的实际结果。