Python打印速度令人难以置信

时间:2016-06-10 01:08:24

标签: r python-3.x numpy io rpy2

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

我的输入文件很大(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()

2 个答案:

答案 0 :(得分: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"在标签上,它在所有代码的任何情况下都是高性能的。您是否考虑通过代码分析器运行缓慢的最后一个循环?它会告诉你花费的时间。

答案 1 :(得分:1)

首先,我通常使用生成器来避免许多小字符串的临时列表。

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

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