减少长时间运行应用程序中的numpy内存占用

时间:2012-09-14 10:04:03

标签: python memory-management numpy garbage-collection

在我的应用程序中,生成100个numpy数组(每个1000个复杂元素)并填充数据。然后经过多次迭代,一遍又一遍地修改数组元素。在初始生成之后,系统监视器报告大约50 Mb的RAM使用情况。虽然我没有生成任何新阵列,但每次迭代的足迹仍然增长了大约40 Mb。

我学会了here,垃圾收集器不处理numpy数组。所以我假设我生成的一些临时数组没有正确收集。

Here不幸的是,guppy.hpy()。heap()无法帮助分析numpy。

如何确定问题的根源,理想情况下,在任意次数的迭代中保持消耗不变?

我怀疑在分配here所描述的数组元素时,我可能会生成副本,然后不会进行垃圾回收。

我可以手动处理临时numpy数组以协助垃圾回收吗?

[更新1]:示例代码

这段代码被调用数千次。每次,足迹都会增加。我不明白为什么,因为根据我的理解,它只是读取现有数组并操纵其他现有数组。这些切片操作中的任何一个都是无意中做的吗? (对不起行长。我可以简化它,但我也可能隐藏我的错误。)

for ts in np.arange(numTimeslots):
            for fc in np.arange(numFreqChunks):
                interfencep = np.sum( np.dot(np.dot(self.baseStations[bs].cells[cell].CSI_OFDMA[:,:,fc,ts] ,np.diag(cell.OFDMA_power[:,fc,ts])),self.baseStations[bs].cells[cell].CSI_OFDMA[:,:,fc,ts].conj().T) for bs in self.baseStations for cell in bs.cells if cell != self._cell) 
                noisep = np.eye(self.antennas) * (self.noisePower / numFreqChunks)
                self.OFDMA_interferenceCovar[:,:,fc,ts] = noisep + interfencep
                self.OFDMA_EC[:,:,fc,ts] = (np.dot(np.dot(self.OFDMA_CSI[:,:,fc,ts],linalg.inv(noisep+interfencep)),self.OFDMA_CSI[:,:,fc,ts].conj().T))
                eigs = linalg.eig(self.OFDMA_EC[:,:,fc,ts])[0]
                self.OFDMA_SINR[:,fc,ts] = np.real(eigs)

[更新2]:对于那些好奇的人来说,这是移动网络模拟器的一部分。运行virtualenv,Python 2.7.3,Numpy 1.6.2,SciPy 0.11.0b1

[更新3]:通过评论并检查系统监视器,我可以将'interferencep = ...' - 行识别为罪魁祸首。它分配了大量未释放的内存。但为什么呢?

2 个答案:

答案 0 :(得分:5)

我遇到了同样的问题。不幸的是我找不到解决方法。唯一对我有用的是将代码重构为小的独立函数。应该制作这些函数,以便我可以说服自己我没有引用数组来阻止垃圾收集器收集数组。你应该特别注意通过切片等生成的数组视图......

为了使代码更高效,更不容易出现内存泄漏,我经常发现使用许多numpy函数提供的out = keyword参数很有用。

答案 1 :(得分:2)

通过使用系统监视器和代码检查/注释,我发现了内存泄漏。这是通过将numpy数组与不同文件中的空列表进行比较而引起的。我将在不同的地方挖掘泄漏并投票删除这个问题,因为我觉得它太具体了,无法帮助其他人。

[更新1]:描述问题根源的新问题: Why does comparison of a numpy array with a list consume so much memory?