我想将子进程(和线程)模块用于:
因为这是核苷酸分辨率的基因组规模数据,取决于基因组大小。对于真实的人类数据,将子进程输出写入临时文件可能需要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倍,我该怎么做才能改善这一点?使用临时文件时的速度增益特别令人惊讶,考虑到我一个接一个地处理它。