我试图理解为什么在函数和独立函数中使用numpy.loadtxt
时,我会得到非常不同的分析/时序数。
假设我有一个名为'test.out'的文件,其中包含以上属性:
>>> f = open('test.out', 'r');f.readline()
'a b c d e f g h i j k l m n o p q r s t u v w x y z\n'
>>> %timeit -n 1 np.loadtxt(f, unpack=True)
1 loops, best of 3: 30 us per loop
现在我想在ipython中的函数内部(使用line_profiler)和numpy.loadtxt
magic中分析%lrpun
:
>>> %lprun -f file_to_numpy_ordered_dict file_to_numpy_ordered_dict('test.out')
Timer unit: 1e-06 s
Function: file_to_numpy_ordered_dict at line 88
Total time: 0.085642 s
Line # Hits Time Per Hit % Time Line Contents
==============================================================
88 def file_to_numpy_ordered_dict(filename):
89 """
90 Read a space-separated-value file as a dict of columns, keyed by
91 column header where each column (dict value) is a numpy array.
92 """
93
94 1 430 430.0 0.5 with open(filename, 'r') as file_obj:
95 1 363 363.0 0.4 headers = file_obj.readline().split()
96
97 # unpack=True b/c want data organized as column based arrays, not rows
98 1 84634 84634.0 98.8 arrs = np.loadtxt(file_obj, unpack=True)
99
100 1 66 66.0 0.1 ret_dict = collections.OrderedDict()
101 27 34 1.3 0.0 for ii, colname in enumerate(headers):
102 26 114 4.4 0.1 ret_dict[colname] = arrs[ii]
103
104 1 1 1.0 0.0 return ret_dict
为什么调用numpy.loadtxt本身只需30us并在此函数内调用它大约需要0.085秒?我觉得这里有一些显而易见的东西,但看起来在每个场景中使用相同的参数调用函数完全相同,等等。
这是一个奇怪的区别,因为我正在使用%timeit
和%lprun
?也许这些数据由于某种原因无法进行比较?
使用以下代码生成文件数据: def generate_test_data(column_names,row_count,filename): “”” 生成大小随机测试数据的文件(row_count,len(column_names))
column_names - List of column name strings to use as header row
row_count - Number of rows of data to generate
filename - Name of file to write test data to
"""
col_count = len(column_names)
rand_arr = np.random.rand(row_count, col_count)
header_line = ' '.join(column_names)
np.savetxt(filename, rand_arr, delimiter=' ', fmt='%1.5f',
header=header_line, comments='')
答案 0 :(得分:3)
仅供参考,此问题的“回答”与如何我正在进行性能分析有关,而不是在函数中对numpy.loadtxt
的实际调用更慢或更快。< / p>
小心%timeit
的参数:
-n:在循环中执行给定的语句次数。如果这个值 如果没有给出,则选择拟合值。
-r:重复循环迭代次数并获得最佳结果。 默认值:3
请注意,我指定-n 1
强制%timeit
仅运行numpy.loadtxt
代码1次。但是,-n 1
还不够。您还必须指定-r 1
以强制对代码的评估仅发生一次。
因此,我对%timeit
的电话有效地评估了对numpy.loadtxt
的调用3次。第一个调用实际上将读取所有文件并占用总运行时间的大部分。接下来的两个调用没有要读取的数据,因为传递给numpy.loadtxt
的文件句柄不再有要读取的数据。因此,三分之二的电话没有任何真正的工作要做,几乎没有时间。
%timeit
的报告时间。注意对%timeit
的调用作为其输出的一部分报告的内容,1个循环,最佳3 :每循环30个us。由于我的三个电话中的两个有效地没有工作,因此这两个电话中的一个将是 3中的最佳电话。
通过比较我对%timeit
和%lprun
的原始调用,我有效地比较了查看空/完成文件句柄所需的时间numpy.loadtxt
和时间numpy.loadtxt
需要真正打开并读取完整的208k数据。
当使用%timeit
的正确参数时,实际时间更有意义:
>>> f = open('test.out', 'r');f.readline()
'a b c d e f g h i j k l m n o p q r s t u v w x y z\n'
>>> %timeit -n 1 -r 1 np.loadtxt(f, unpack=True)
1 loops, best of 1: 31.1 ms per loop
Function: file_to_numpy_ordered_dict at line 88
Total time: 0.083706 s
Line # Hits Time Per Hit % Time Line Contents
==============================================================
88 def file_to_numpy_ordered_dict(filename):
89 """
90 Read a space-separated-value file as a dict of columns, keyed by
91 column header where each column (dict value) is a numpy array.
92 """
93
94 1 583 583.0 0.7 with open(filename, 'r') as file_obj:
95 1 313 313.0 0.4 headers = file_obj.readline().split()
96
97 # unpack=True b/c want data organized as column based arrays, not rows
98 1 82417 82417.0 98.5 arrs = np.loadtxt(file_obj, unpack=True)
99
100 1 226 226.0 0.3 ret_dict = collections.OrderedDict()
101 27 35 1.3 0.0 for ii, colname in enumerate(headers):
102 26 131 5.0 0.2 ret_dict[colname] = arrs[ii]
103
104 1 1 1.0 0.0 return ret_dict
31ms vs 83 ms 更有意义。这些数字足够接近我假设差异仅仅是因为我只是一次运行这个相对较快的操作。为了有效地比较它们,最好平均进行一系列运行。