numpy.loadtxt的分析结果的差异

时间:2013-03-08 15:15:19

标签: python numpy

我试图理解为什么在函数和独立函数中使用numpy.loadtxt时,我会得到非常不同的分析/时序数。

设置要读取/配置文件的数据

  • 1个文件,包含26列和1000行,文件中的每个项目都是随机浮点数
  • 文件是空格分隔的
  • 文件中的第一行是一个空格分隔的标题,包含26个列名
  • 请参阅下文,了解有关如何生成此数据的代码

仅分析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

在函数

内分析numpy.loadtxt

现在我想在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='')
    

1 个答案:

答案 0 :(得分:3)

仅供参考,此问题的“回答”与如何我正在进行性能分析有关,而不是在函数中对numpy.loadtxt的实际调用更慢或更快。< / p>

  1. 小心%timeit的参数:

    -n:在循环中执行给定的语句次数。如果这个值 如果没有给出,则选择拟合值。

    -r:重复循环迭代次数并获得最佳结果。 默认值:3

  2. 请注意,我指定-n 1强制%timeit仅运行numpy.loadtxt代码1次。但是,-n 1还不够。您还必须指定-r 1以强制对代码的评估仅发生一次

    因此,我对%timeit的电话有效地评估了对numpy.loadtxt的调用3次。第一个调用实际上将读取所有文件并占用总运行时间的大部分。接下来的两个调用没有要读取的数据,因为传递给numpy.loadtxt的文件句柄不再有要读取的数据。因此,三分之二的电话没有任何真正的工作要做,几乎没有时间

    1. 请注意%timeit的报告时间。
    2. 注意对%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 更有意义。这些数字足够接近我假设差异仅仅是因为我只是一次运行这个相对较快的操作。为了有效地比较它们,最好平均进行一系列运行。