代码之家  ›  专栏  ›  技术社区  ›  chimeracoder

Python中的概要文件内存分配(支持Numpy数组)

  •  27
  • chimeracoder  · 技术社区  · 16 年前

    我有一个包含大量对象的程序,其中很多是Numpy数组。我的程序交换得很惨,我正试图减少内存使用,因为它实际上无法用当前的内存需求来限制我的系统。

    我正在寻找一个很好的分析器,可以让我检查由各种对象消耗的内存量(我正在设想一个与cProfile相对应的内存),以便我知道在哪里进行优化。

    我听说过Heapy的一些不错的东西,但是Heapy很不幸不支持Numpy数组,而且我的大多数程序都涉及Numpy数组。

    5 回复  |  直到 16 年前
        1
  •  12
  •   Fabian Pedregosa    12 年前

    如果您调用了许多不同的函数,并且不确定交换的来源,那么解决这个问题的一种方法是使用 memory_profiler . 首先,您必须装饰您使用@profile的不同功能。为了简单起见,我将使用这个示例 examples/numpy_example.py 内存配置文件器附带有两个功能: create_data() process_data()

    要运行脚本,而不是使用Python解释器运行它,可以使用mprof可执行文件,即

    $ mprof run examples/numpy_example.py
    

    这将创建一个名为 mprofile_??????????.dat ,在哪里?将保留代表当前日期的数字。要绘制结果,只需键入 mprof plot 它将生成与此类似的绘图(如果您有多个.dat文件,则始终使用最后一个):

    output of memory_profiler's mprof

    在这里您可以看到内存消耗情况,括号表示何时进入/离开当前函数。这样就很容易看到这个函数 处理数据() 有一个高峰 内存消耗。要进一步深入了解函数,可以使用逐行分析器查看函数中每一行的内存消耗。这是和

    python -m memory_profiler examples/nump_example.py
    

    这将为您提供类似的输出:

    Line #    Mem usage    Increment   Line Contents
    ================================================
        13                             @profile
        14  223.414 MiB    0.000 MiB   def process_data(data):
        15  414.531 MiB  191.117 MiB       data = np.concatenate(data)
        16  614.621 MiB  200.090 MiB       detrended = scipy.signal.detrend(data, axis=0)
        17  614.621 MiB    0.000 MiB       return detrended
    

    很明显,scipy.signal.detrend正在分配大量内存。

        2
  •  10
  •   bmu    12 年前

    看一看 memory profiler . 它提供逐行分析和 Ipython 集成,使用起来非常方便:

    In [1]: import numpy as np
    
    In [2]: %memit np.zeros(1e7)
    maximum of 3: 70.847656 MB per loop
    

    更新

    正如@wickedgedrey提到的,好像有一只虫子( see github issue tracker )当多次调用一个函数时,我可以重现:

    In [2]: for i in range(10):
       ...:     %memit np.zeros(1e7)
       ...:     
    maximum of 1: 70.894531 MB per loop
    maximum of 1: 70.894531 MB per loop
    maximum of 1: 70.894531 MB per loop
    maximum of 1: 70.894531 MB per loop
    maximum of 1: 70.894531 MB per loop
    maximum of 1: 70.894531 MB per loop
    maximum of 1: 70.902344 MB per loop
    maximum of 1: 70.902344 MB per loop
    maximum of 1: 70.902344 MB per loop
    maximum of 1: 70.902344 MB per loop
    

    然而,我不知道结果可能会影响到什么程度(在我的示例中似乎没有那么多,因此根据您的用例,它可能仍然有用)以及这个问题何时可能得到解决。我是在 github .

        3
  •  1
  •   letmaik    12 年前

    由于NUMPY 1.7存在一个半内置的方式来跟踪内存分配:

    https://github.com/numpy/numpy/tree/master/tools/allocation_tracking

        4
  •  0
  •   Samizdis    16 年前

    在不使用tmp文件时,可以将一些数组保存/pickle到磁盘吗?这就是我过去在处理大型数组时必须做的事情。当然这会减慢程序的速度,但至少它会完成。除非你一下子就需要它们?

        5
  •  0
  •   Bastian Venthur    12 年前

    你试过了吗 valgrind massif 工具?

    valgrind --tool=massif python yourscript.py
    

    它将创建一个名为 massif.out.xxx 你可以通过

    ms_print massif.out.xxx | less
    

    它有各种有用的信息,但一开始的情节应该是你要找的。也可以退房 massif tutorial 在valgrind主页上。

    使用 瓦尔格林 是相当先进的,可能有更容易的方法做你想找的。