管道从子进程到线程进程的数据

时间:2015-04-14 21:51:03

标签: python multithreading python-2.7 subprocess

我想将子进程(和线程)模块用于:

  1. 调用将二进制文件处理为人类可读输出的程序
  2. 处理子流程的输出
  3. 做1& 2同时进行两次重复(如果可能)
  4. 因为这是核苷酸分辨率的基因组规模数据,取决于基因组大小。对于真实的人类数据,将子进程输出写入临时文件可能需要500GB的空间,如果可能的话我想避免这种情况。

    我尝试了两种策略,一种是将子进程输出保存在临时文件中,另一种是使用带有Popen的stdout = subprocess.PIPE选项。无论哪种方式,这都是我的速率限制步骤,当我使用真实数据集时会变得有限制。

    仅使用子进程模块的临时文件:

    SC_paste_rep1 = subprocess.Popen(["bwtool","paste","typeA_rep1","typeB_rep1","-o=tmp_file_rep1.bg"])
    SC_pasteM_rep2 = subprocess.Popen(["bwtool","paste","typeA_rep2","typeB_rep2","-o=tmp_file_rep2.bg"])
    
    SC_paste_rep1.wait()
    SC_paste_rep2.wait()
    

    然后我一个接一个地遍历每个临时文件,并处理这些行(使用看起来像下面代码块中的f()的东西)。当我在测试集上计算我的脚本时,我得到:
       真正的7m9.100s
       用户8m43.162s
       sys 0m21.572s

    我的第二次尝试避开了临时文件并使用了子进程和线程:

    def struct_bind(input_pipe, output_pipe, calc_structScore):
            def f():
                try:
                    DS_old_val = ''
                    SS_old_val = ''
                    old_chr = ''
                    start_set = ''
                    stop_set = ''
                    for line in iter(input_pipe.readline, ''):
                        (out_line,start_set,stop_set,old_chr,DS_old_val,SS_old_val) = calc_structScore(line,start_set,stop_set,old_chr,DS_old_val,SS_old_val)
                        if out_line != "hold":
                            output_pipe.write(out_line)
                finally:
                    try:
                        output_pipe.close()
                    finally:
                        input_pipe.close()
            t = threading.Thread(target=f)
            t.daemon = True
            t.start()
            return t
    
    output_rep1_open = open("output_rep1.bw",'w')
    output_rep2_open = open("output_rep2.bw",'w')
    
    SC_paste_rep1 = subprocess.Popen(["bwtool","paste","typeA_rep1","typeB_rep1"],stdout=subprocess.PIPE,bufsize=-1)
    SC_mod_rep1 = struct_bind(SC_paste_rep1.stdout,output_rep1_open,calc_structScore)
    
    SC_paste_rep2 = subprocess.Popen(["bwtool","paste","typeA_rep2","typeB_rep2"],stdout=subprocess.PIPE,bufsize=-1)
    SC_mod_rep2 = struct_bind(SC_paste_rep2.stdout,output_rep2_open,calc_structScore)
    
    SC_mod_rep1.join()
    SC_mod_rep2.join()
    SC_paste_rep1.wait()
    SC_paste_rep2.wait()
    

    当我用bufsize = -1:
    计算时间     真实11m59.916s
        用户15m15.790s
        sys 6m4.131s

    并且bufsize = 0:
        真实的25m11.939s
        用户26m11.768s
        sys 25m46.414s


    在真实数据集上,使用临时文件我可以得到:
        真正的151m3.040s
        用户172m4.584s
        sys 8m33.428s

    没有我可以得到:
        真正的248m52.712s
        用户301m30.378s
        sys 151m23.694s

    我的管道策略有什么问题,使得使用临时文件的速度提高了2倍,我该怎么做才能改善这一点?使用临时文件时的速度增益特别令人惊讶,考虑到我一个接一个地处理它。

0 个答案:

没有答案