2016-06-10 187 views
1

我遇到了一个我从未遇到过的问题,这让我非常沮丧。我正在使用rpy2从python脚本中与R接口,并规范化数组。出于某种原因,当我将打印输出一起打印到文件时,需要打印年龄。它也会随着它的进行而减慢,直到它可能每分钟输出几kb的数据。Python打印速度非常慢

我的输入文件很大(366 MB),但是这是在高性能计算群集上运行的,具有近似无限的资源。这应该没有问题。

这里就是我实际上做归一化:

matrix = sample_list # two-dimensional array 
v = robjects.FloatVector([ element for col in matrix for element in col ]) 
m = robjects.r['matrix'](v, ncol = len(matrix), byrow=False) 
print("Performing quantile normalization.") 
Rnormalized_matrix = preprocessCore.normalize_quantiles(m) 
normalized_matrix = np.array(Rnormalized_matrix) 

正如你所看到的,我结束了我的含现在规范化的数据numpy.array对象。我还有另一个包含其他字符串的列表,我想将其输出到输出中,每个元素对应于numpy数组的一个元素。所以我迭代,将数组的每一行连接到一个字符串并打印输出。

for thing in pos_list: # List of strings corresponding with each row of array. 
    thing_index = pos_list.index(thing) 

    norm_data = normalized_matrix[thing_index] 
    out_data = "\t".join("{0:.2f}".format(piece) for piece in norm_data) 

    print(thing + "\t" + out_data, file=output) 

我不是职业球员,但我不知道为什么事情都放缓了这么多。任何见解或建议将非常非常感激。如果有人认为它可能有帮助,我可以发布更多/脚本的其余部分。

更新: 感谢@lgautier提供的分析建议。使用line_profiler模块,我能我的问题找准前往路线: thing_index = pos_list.index(thing)

这是有道理的,因为这个名单很长,而且也解释了减缓的剧本进行。只需使用计数来解决问题。

的原代码分析(注意指定的线路%):

Line #  Hits   Time Per Hit % Time Line Contents 
    115   1  16445761 16445761.0  15.5  header, pos_list, normalized_matrix = Quantile_Normalize(in 
    117   1   54  54.0  0.0   print("Creating output file...") 
    120   1   1450 1450.0  0.0   output = open(output_file, "w") 
    122   1   8  8.0  0.0   print(header, file=output) 
    124             # Iterate through each position and print QN'd data 
    125 100000  74600  0.7  0.1   for thing in pos_list: 
    126  99999  85244758 852.5  80.3     thing_index = pos_list.index(thing) 
    129  99999  158741  1.6  0.1     norm_data = normalized_matrix[thing_index] 
    130  99999  3801631  38.0  3.6     out_data = "\t".join("{0:.2f}".format(piece) for pi 
    132  99999  384248  3.8  0.4     print(thing + "\t" + out_data, file=output) 
    134   1   3641 3641.0  0.0   output.close() 

剖析新代码:

Line #  Hits   Time Per Hit % Time Line Contents 
    115   1  16177130 16177130.0  82.5  header, pos_list, normalized_matrix = Quantile_Normalize(input_file, data_start) 
    116 
    117   1   55  55.0  0.0   print("Creating output file...") 
    118 
    119 
    120   1  26157 26157.0  0.1   output = open(output_file, "w") 
    121 
    122   1   11  11.0  0.0   print(header, file=output) 
    123 
    124             # Iterate through each position and print QN'd data 
    125   1   1  1.0  0.0   count = 0 
    126 100000  62709  0.6  0.3   for thing in pos_list: 
    127  99999  58587  0.6  0.3     thing_index = count 
    128  99999  67164  0.7  0.3     count += 1 
    131  99999  85664  0.9  0.4     norm_data = normalized_matrix[thing_index] 
    132  99999  2877634  28.8  14.7     out_data = "\t".join("{0:.2f}".format(piece) for piece in norm_data) 
    134  99999  240654  2.4  1.2     print(thing + "\t" + out_data, file=output) 
    136   1   1713 1713.0  0.0   output.close() 
+0

pos_list是否包含R对象?我不经常使用rpy2,但根据我的经验,这两种语言之间的交互相当缓慢。 –

+0

什么部分实际上很慢?尝试评论一些零碎的东西,看看是什么让它变得更快。我期望'[col中元素的矩阵元素]'很慢。 –

+0

不,pos_list只包含字符串。 col中元素列表中的元素[col for col]中的元素是缓慢的,但它在任何实际输出到文件之前,所以它不是这里的瓶颈。 –

回答

2

如果我理解这个正确的一切都运行良好,并具有良好的性能高达(包括)行:

normalized_matrix = np.array(Rnormalized_matrix) 

在该行所得到的矩阵变成一个numpy的阵列(字面意思 - 它在避免复制数据时可以更快,如http://rpy2.readthedocs.io/en/version_2.8.x/numpy.html?from-rpy2-to-numpy)。

我看不到有关rpy2的脚本其余部分的性能问题。

现在可能发生的情况是,这不是因为它在标签上显示“HPC”,它在所有代码的任何情况下都具有高性能。您是否考虑过通过代码分析器运行最后一个循环?它会告诉你时间花在哪里。

+0

因此,使用'line_profiler'模块,我能够确定~80%的时间花在这一行上:'thing_index = pos_list.index(thing)',我猜这应该是明显的,因为该文件是数以百万计的线路,并随着它的进一步进一步搜索而变慢。我用一个计数器取代了它,并且看到了大幅加速。对我而言,这是一个巨大的疏忽,但随着你的回答让我走向正确的策略,我将其标记为答案。我会更新我的问题以反映分析和更改。 –

1

一两件事,我通常使用一台发电机,以避免临时列表许多细小的弦。

out_data = "\t".join("{0:.2f}".format(piece) for piece in norm_data) 

但是很难说这部分是否是缓慢的。

+0

谢谢,这是一个很好的提示。我已经用它更新了我的代码,尽管它没有解决问题。 –