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

chi*_*der 27 python profile memory-management numpy

我有一个包含大量对象的程序,其中许多是Numpy数组.我的程序很糟糕地交换,我正在尝试减少内存使用量,因为它实际上无法在我的系统上使用当前的内存要求.

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

我听说过关于Heapy的不错的东西,但遗憾的是Heapy不支持Numpy数组,而且我的大多数程序都涉及Numpy数组.

Fab*_*osa 12

解决问题的一种方法是,如果要调用许多不同的函数,并且不确定交换的来源是使用memory_profiler中的新绘图功能.首先,您必须使用@profile修饰您正在使用的不同功能.为简单起见,我会使用示例例子/ numpy_example.py附带了包含两个功能memory_profiler:create_data()process_data()

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

$ mprof run examples/numpy_example.py
Run Code Online (Sandbox Code Playgroud)

这将创建一个名为的文件mprofile_??????????.dat,其中?将保存代表当前日期的数字.要绘制结果,只需键入mprof plot,它将生成类似于此的绘图(如果您有几个.dat文件,它将始终采用最后一个):

memory_profiler的mprof输出

在这里您可以看到内存消耗,括号表示您何时进入/离开当前功能.这样很容易看出函数process_data()有内存消耗的高峰.要进一步深入了解您的功能,您可以使用逐行分析器来查看函数中每行的内存消耗.这是运行

python -m memory_profiler examples/nump_example.py
Run Code Online (Sandbox Code Playgroud)

这会给你一个类似于这样的输出:

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
Run Code Online (Sandbox Code Playgroud)

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


bmu*_*bmu 10

看一下内存分析器.它提供逐行分析和Ipython集成,这使得它非常容易使用:

In [1]: import numpy as np

In [2]: %memit np.zeros(1e7)
maximum of 3: 70.847656 MB per loop
Run Code Online (Sandbox Code Playgroud)

更新

正如@WickedGrey所提到的,在多次调用函数时似乎存在一个错误(参见github问题跟踪器),我可以重现:

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
Run Code Online (Sandbox Code Playgroud)

但是我不知道结果可能影响到什么范围(在我的例子中似乎没那么多,所以根据你的用例它可能仍然有用)并且当这个问题可能修复时.我在github问过.


Sam*_*dis 0

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

  • 嗯,是的,但是分析的重点是我想找出应该写入文件的*哪些*数组。如果我尝试编写所有内容并仅在需要时才拉取它,那么 I/O 需求将非常巨大,并且会违背这一点。 (3认同)