我有一个包含大量对象的程序,其中许多是Numpy数组。我的程序很糟糕地交换,我正在尝试减少内存使用量,因为它实际上无法在我的系统上完成当前的内存需求。
我正在寻找一个好的分析器,它可以让我检查各种对象消耗的内存量(我正在设想与cProfile相对应的内存),以便我知道在哪里进行优化。
我听说过关于Heapy的不错的东西,但遗憾的是Heapy不支持Numpy数组,而且我的大多数程序都涉及Numpy数组。
答案 0 :(得分:12)
如果要调用许多不同的函数并且不确定交换来自何处,那么解决问题的一种方法是使用memory_profiler中的新绘图功能。首先,您必须使用@profile装饰您正在使用的不同功能。为简单起见,我将使用memory_profiler附带的示例examples/numpy_example.py,其中包含两个函数:create_data()
和process_data()
要运行脚本,而不是使用Python解释器运行它,请使用mprof可执行文件,即
$ mprof run examples/numpy_example.py
这将创建一个名为mprofile_??????????.dat
的文件,其中?将保存代表当前日期的数字。要绘制结果,只需键入mprof plot
,它就会生成一个与此类似的图(如果你有几个.dat文件,它将始终采用最后一个):
在这里您可以看到内存消耗,括号表示您何时进入/离开当前功能。这样很容易看出函数process_data()
有一个峰值
内存消耗要进一步深入了解您的功能,您可以使用逐行分析器来查看函数中每行的内存消耗。这是用
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正在分配大量内存。
答案 1 :(得分:10)
看看memory profiler。它提供逐行分析和Ipython
集成,这使得它非常容易使用:
In [1]: import numpy as np
In [2]: %memit np.zeros(1e7)
maximum of 3: 70.847656 MB per loop
<强>更新强>
正如@WickedGrey所提到的,在多次调用函数时似乎存在一个错误(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问了那个问题。
答案 2 :(得分:1)
由于numpy 1.7存在一种半内置的方式来跟踪内存分配:
https://github.com/numpy/numpy/tree/master/tools/allocation_tracking
答案 3 :(得分:0)
在不使用tmp文件时,你能将一些数组保存/腌制到磁盘吗?这就是我过去使用大型阵列时必须做的事情。当然这会减慢程序,但至少它会完成。除非你一次性需要它们吗?
答案 4 :(得分:0)
您是否使用valgrind
工具尝试massif
?
valgrind --tool=massif python yourscript.py
它将创建一个名为massif.out.xxx
的文件,您可以通过
ms_print massif.out.xxx | less
它有各种有用的信息,但一开始的情节应该是你正在寻找的。另请查看valgrind主页上的massif tutorial。
使用valgrind
非常先进,可能有更简单的方法来执行您正在寻找的内容。