8

在我的应用程序中,生成了一百个 numpy 数组(每个数组 1000 个复杂元素)并填充了数据。然后经过多次迭代,数组元素被一遍又一遍地修改。初始生成后,系统监视器报告大约 50 Mb 的 RAM 使用情况。尽管我没有生成任何新数组,但每次迭代的占用空间会持续增长约 40 Mb。

我在这里了解到,垃圾收集器不处理 numpy 数组。所以我假设我为操作数据而生成的一些临时数组没有正确收集。

不幸的是,这里说 guppy.hpy().heap() 对分析 numpy 没有帮助。

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

我怀疑我在分配数组元素时可能会生成副本,如此处所述这些副本不会被垃圾收集。

我可以手动处理临时 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 = ...' 行识别为罪魁祸首。它分配了未释放的大量内存。但为什么?

4

2 回答 2

6

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

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

于 2012-09-14T11:06:23.497 回答
2

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

[更新 1]:描述问题根源的新问题: 为什么将 numpy 数组与列表进行比较会消耗这么多内存?

于 2012-09-17T13:32:13.373 回答