Python 打印速度慢得令人难以置信

Python Printing Incredibly Slowly

我 运行 遇到了一个我以前从未遇到过的问题,这让我非常沮丧。我正在使用 rpy2 从 python 脚本中与 R 交互并规范化数组。出于某种原因,当我将输出拼凑并打印到文件时,需要 ages 才能打印。随着它的进行,它也会减慢速度,直到它每分钟可能输出几 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)

我不是专业人士,但我不知道为什么事情进展如此缓慢。任何见解或建议将非常非常感谢。如果有人认为它可能有帮助,我可以 post more/the 脚本的其余部分。

更新: 感谢@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()

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

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

但是很难说这部分是不是慢的部分。

如果我理解正确,一切 运行 都很好,并且性能良好,直到(包括)以下行:

normalized_matrix = np.array(Rnormalized_matrix)

在那一行,结果矩阵变成了一个 numpy 数组(从字面上看 - 在避免复制数据时它可以更快,如 http://rpy2.readthedocs.io/en/version_2.8.x/numpy.html?from-rpy2-to-numpy )。

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

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