在python中并行化for循环

时间:2014-02-13 10:39:39

标签: python loops parallel-processing biopython

我有一套简单的代码来运行Python中的Clustal Omega(蛋白质多序列比对程序):

from Bio.Align.Applications import ClustalOmegaCommandline

segments = range(1, 9)
segments.reverse()

for segment in segments:
    in_file = '1.0 - Split FASTA Files/Segment %d.fasta' % segment
    out_file = '1.1 - Aligned FASTA Files/Segment %d Aligned.fasta' % segment
    distmat = '1.1 - Distmats/Segment %d Distmat.fasta' % segment

    cline = ClustalOmegaCommandline(infile=in_file, 
                                    outfile=out_file, 
                                    distmat_out=distmat, 
                                    distmat_full=True, 
                                    verbose=True,
                                    force=True)
    print cline
    cline()

我已经完成了一些非正式测试,计时我的多序列比对(MSA)需要多长时间。平均每人需要4个小时。一个接一个地跑完全8个,总共花了我32个小时。因此,这是我最初将其作为for循环运行的意图 - 我可以让它运行而不用担心它。

然而,我做了另一次非正式测试 - 我从打印的cline中取出输出,并将其复制并粘贴到分布在两台计算机上的8个独立的终端窗口中,并以这种方式运行MSA。平均而言,每个人花了大约8个小时左右......但由于他们都在同一时间运行,我花了8个小时才得到结果。

在某些方面,我发现了并行处理! :d

但我现在面临着如何让它在Python中运行的困境。我已经尝试过查看以下SO帖子,但我仍然无法理解多处理模块的工作原理。

帖子列表:

有人愿意分享他们如何并行化这个循环吗?我看起来很多循环看起来类似于这个循环,我在其中对文件执行一些操作并写入另一个文件,而不需要将结果聚合在内存中。我面临的具体差异是需要进行文件I / O,而不是循环并行运行的聚合结果。

2 个答案:

答案 0 :(得分:3)

Joblib library可能就是你要找的东西。

让我举一个使用它的例子:

import time
from joblib import Parallel, delayed


def long_function():
    time.sleep(1)


REPETITIONS = 4
Parallel(n_jobs=REPETITIONS)(
    delayed(long_function)() for _ in range(REPETITIONS))

此代码在1秒内运行,而不是4秒。

调整代码看起来像这样(对不起,我无法测试这是否正确):

from joblib import Parallel, delayed

from Bio.Align.Applications import ClustalOmegaCommandline


def run(segment):
    in_file = '1.0 - Split FASTA Files/Segment %d.fasta' % segment
    out_file = '1.1 - Aligned FASTA Files/Segment %d Aligned.fasta' % segment
    distmat = '1.1 - Distmats/Segment %d Distmat.fasta' % segment
    cline = ClustalOmegaCommandline(infile=in_file,
                                    outfile=out_file,
                                    distmat_out=distmat,
                                    distmat_full=True,
                                    verbose=True,
                                    force=True)
    print cline
    cline()


if __name__ == "__main__":
    segments = range(1, 9)
    segments.reverse()

    Parallel(n_jobs=len(segments)(
        delayed(run)(segment) for segment in segments)

答案 1 :(得分:1)

而不是for segment in segments,请写def f(segment),然后使用multiprocessing.Pool().map(f, segments)

弄清楚如何将其置于上下文中留给读者练习。