Печать на Python невероятно медленно
Я сталкиваюсь с проблемой, с которой я никогда не сталкивался, и это чертовски расстраивает меня. я использую rpy2
взаимодействовать с R
из скрипта Python и нормализовать массив. По какой-то причине, когда я собираю свои выходные данные вместе и печатаю в файл, на печать уходит целая вечность. Он также замедляется по мере продолжения, пока не будет сброшено, возможно, несколько килобайт данных для вывода в минуту.
Мой входной файл большой (366 МБ), но он работает на высокопроизводительном вычислительном кластере с почти неограниченными ресурсами. Не должно быть никаких проблем с этим.
Вот где я на самом деле делаю нормализацию:
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 ответа
Если я правильно понимаю, все работает нормально и с хорошей производительностью вплоть до (и в том числе) строки:
normalized_matrix = np.array(Rnormalized_matrix)
В этой строке результирующая матрица превращается в пустой массив (буквально - это может быть даже быстрее, если избежать копирования данных, как в http://rpy2.readthedocs.io/en/version_2.8.x/numpy.html?from-rpy2-to-numpy).
Я не вижу проблем с производительностью в остальной части скрипта, связанной с rpy2.
Теперь может случиться так, что это не потому, что на этикетке написано "HPC", что он высокопроизводителен в любой ситуации со всем кодом. Вы рассматривали возможность запуска этого медленного последнего цикла через профилировщик кода? Это скажет вам, где время проведено.
Во-первых, я обычно использую генератор, чтобы избежать временного списка множества маленьких строк.
out_data = "\t".join("{0:.2f}".format(piece) for piece in norm_data)
Но трудно сказать, была ли эта часть медленной.