使用Linux上没有出现的长列表时的Python MemoryError

时间:2013-10-23 13:56:38

标签: python linux windows python-2.7 memory-management

我开始使用一个相当大的模拟代码,需要存储最多189383040个浮点数。我知道,这很大,但是没有太多办法可以解决这个问题,比如只看一部分或逐个处理它们。

我写了一个简短的脚本,它会重现错误,所以我可以在不同的环境中快速测试它:

noSnapshots = 1830
noObjects = 14784

objectsDict={}

for obj in range(0, noObjects):
    objectsDict[obj]=[[],[],[]]
    for snapshot in range(0,noSnapshots):
        objectsDict[obj][0].append([1.232143454,1.232143454,1.232143454])
        objectsDict[obj][1].append([1.232143454,1.232143454,1.232143454])
        objectsDict[obj][2].append(1.232143454)

它表示实际代码的结构,其中必须为lists147841830个对象存储一些参数(每个长度为3 {1}}且1个浮点数)位置。显然,每次对于不同的对象,数字会有所不同,但在我的代码中,我只是去了一些随机输入的数字。

我觉得这并不奇怪的是,它在Windows 7企业版和家庭高级版上失败了MemoryError。即使我在具有16 GB RAM的机器上运行代码,它仍然会失败,即使机器上仍有大量内存。所以第一个问题是:为什么会这样?我想我的内存越多,内存就越多。

我在我的同事的Ubuntu 12.04机器上运行相同的代码(再次使用16 GB的RAM),它完成没问题。所以我想知道的另一件事是:我能做些什么来让Windows满意这段代码吗?即在堆和堆栈上为我的Python进程提供更多内存吗?

最后:有没有人对如何以与示例代码中的方式类似的方式在内存中存储大量数据有任何建议?

修改

在答案之后我将代码更改为:

import numpy

noSnapshots = 1830
noObjects = int(14784*1.3)

objectsDict={}

for obj in range(0, noObjects):
    objectsDict[obj]=[[],[],[]]

    objectsDict[obj][0].append(numpy.random.rand(noSnapshots,3))
    objectsDict[obj][1].append(numpy.random.rand(noSnapshots,3))
    objectsDict[obj][2].append(numpy.random.rand(noSnapshots,1))

尽管需要存储大量数据,但它仍可正常工作。

1 个答案:

答案 0 :(得分:1)

在Python中,每个float都是堆上的对象,具有自己的引用计数等。对于存储这么多浮点数,你真的应该使用列表的密集表示浮点数,例如numpy的{​​{1}}。

此外,由于您正在重复使用相同的ndarray个对象,因此您无法正确估计内存使用情况。您有对同一个float对象的引用列表。在实际情况下(float s不同),你的内存使用会更高。你真的应该使用float