2014-02-13 155 views
0

我有一组简单的代码运行的Clustal欧米茄在Python(一种蛋白质多序列比对程序):并行化for循环蟒蛇

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循环运行 - 我可以让它运行而不用担心。然而,我做了另一个非正式的测试 - 我从印刷的斜面上得到了输出,并将它复制并粘贴到分布在两台计算机上的8个独立终端窗口中,并以这种方式运行MSA。平均每个人花了大约8个小时左右...但是因为他们都在同一时间运行,我只花了8个小时才得到结果。

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

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

名单职位:

会有人友好地分享他们如何并行这个循环?我做的许多循环看起来类似于这个循环,其中我对文件执行一些操作并写入另一个文件,而不需要将结果聚集在内存中。我所面对的特定差异是需要执行文件I/O,而不是并行运行循环的汇总结果。

+4

由于其他职位已注明多种方式来实现'for'循环的并行化,有某些*特定的*会给你带来麻烦? –

+0

没有任何示例处理文件I/O,而是处理汇总并行运行的结果。至少,这是我在阅读帖子时的想法。请原谅我的无知,我仍然认为自己是许多计算概念和Python的新手。 – ericmjl

+0

如果文件I/O是你所关心的问题,请在问题中明确*。就目前而言,它与您所链接的问题完全相同。但是,AFAIK,文件I/O没有什么特别的。你只需要在进程之间使用一些锁,以避免输出到文件的无意义,你就完成了。 – Bakuriu

回答

2

可能是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) 
+0

感谢您的帮助!我可以问一下,假设这是从IPython笔记本运行的,我是否会将'if __name__ =='__main __':'放在一个单元格中,然后运行该单元格? – ericmjl

+1

是的,如果代码的其余部分包含在已经评估过的前一个单元格中,则可以按照前面所述的方式运行它。 – logc

+0

非常感谢@logc! – ericmjl

1

代替for segment in segments,写def f(segment)然后用multiprocessing.Pool().map(f, segments)

搞清楚这一背景下被作为练习留给读者如何把。

+0

我认为使用'imap'而不是'map'可能适合这里,因为运行时间很长。 – msvalkon