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文件,它将始终采用最后一个):

在这里您可以看到内存消耗,括号表示您何时进入/离开当前功能.这样很容易看出函数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问过.
您可以在不使用某些数组时将它们保存/pickle 到磁盘上的 tmp 文件中吗?这就是我过去必须对大型数组所做的事情。当然,这会减慢程序速度,但至少它会完成。除非你同时需要它们?