【问题标题】:Python MemoryError when using long lists not occurring on Linux使用 Linux 上未发生的长列表时出现 Python MemoryError
【发布时间】:2013-11-01 20:22:55
【问题描述】:

我开始使用一个相当大的模拟代码,它需要存储多达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)

它表示实际代码的结构,其中必须为1830 不同位置的每个14784 对象存储一些参数(2 个lists,每个长度为3,1 个浮点数)。显然,对于不同的对象,每次的数字都会不同,但在我的代码中,我只是选择了一些随机输入的数字。

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

我在同事的 Ubuntu 12.04 机器上运行了相同的代码(同样是 16 GB 的 RAM),它完成了没有问题。所以我想知道的另一件事是:我可以做些什么来让 Windows 对这段代码感到满意吗? IE。给我的 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))

尽管需要存储大量数据,但它仍然有效。

【问题讨论】:

  • 您是否在 Windows 上使用 64 位版本的 Python?
  • 好点。它是 32b Windows 和 64b Linux。
  • 这将 Windows 可用的 RAM 限制为 4GB。
  • @Max 在使用 64b Python 时可以增加这个限制吗?还是升级到 Python 3.X?
  • @AleksanderLidtke:在 Windows 上?请参阅:msdn.microsoft.com/en-us/library/aa366778.aspx。对于 x86(32 位)上的 Windows 7,整个操作系统只能访问 4 GB 的 RAM。 Python 无法再访问了。

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


【解决方案1】:

在 Python 中,每个 float 都是堆上的一个对象,具有自己的引用计数等。为了存储这么多浮点数,您真的应该使用浮点数列表的 密集 表示,比如numpyndarray

另外,因为您正在重用相同的 float 对象,所以您没有正确估计内存使用情况。您有对同一个 float 对象的引用列表。在实际情况下(floats 不同)您的内存使用量会高得多。你真的应该使用ndarray

【讨论】:

  • 是的,我想到了后一点。但是,它确实使程序抛出MemoryError,所以我认为出于测试目的它或多或少是可以的。
  • 对于numpy 数组,它不会那么容易,因为附加它们并不是一个真正的选择,因为没有一种简单的方法可以做到这一点而不会导致周期性的内存跳跃。你会尝试预先分配,但它可能会消耗比需要更多的内存(不是每个对象都有最大数量的条目)。但无论如何,非常感谢您的帮助。
  • @AleksanderLidtke:Python 列表将具有与 ndarray 相同的周期性内存跳转。
  • 我不知道。永远不必担心 python 中的任何内存管理。
  • 我检查了预分配数组,它似乎可以解决问题,即使数组比上面的示例长。非常感谢。
猜你喜欢
  • 2015-11-09
  • 1970-01-01
  • 2020-03-02
  • 1970-01-01
  • 2017-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多