内存错误和列表限制?


68

为了科学目的,我需要产生越来越大的(非常)矩阵(马尔可夫链)。我执行微积分,将其放入20301个元素的列表中(=矩阵的一行)。我需要将所有这些数据存储在内存中以继续进行下一步的马尔可夫步骤,但是如果需要,我可以将它们存储在其他位置(例如文件),即使这会减慢我的马尔可夫链的遍历速度。我的电脑(科学实验室):双氙气6个内核/ 12个线程,12GB内存,操作系统:win64

  Traceback (most recent call last):
  File "my_file.py", line 247, in <module>
    ListTemp.append(calculus)
MemoryError

微积分结果示例:9.233747520008198e-102(是,超过1/9000)

存储第19766个元素时会引发错误:

ListTemp[19766]
1.4509421012263216e-103

如果我走得更远

Traceback (most recent call last):
  File "<pyshell#21>", line 1, in <module>
    ListTemp[19767]
IndexError: list index out of range

因此,此列表在19767循环中发生了内存错误。

问题:

  1. 列表有内存限制吗?是“按列表限制”还是“按脚本全局限制”?

  2. 如何绕过那些限制?有什么想法吗?

  3. 使用numpy,python64是否有帮助?它们的内存限制是多少?那其他语言呢?


3
如果您遇到意外的内存错误,并且认为应该有足够的可用RAM,则可能是因为您使用的是32位python安装。
mgoldwasser

大!哇!好东西,您有这么多的记忆!😉
迈克尔Scheper

Answers:


57

首先,请参阅 Python数组可以达到多大?Numpy,长数组问题

其次,唯一的实际限制来自您拥有的内存量以及系统存储内存引用的方式。没有每个列表的限制,因此Python会一直运行直到内存耗尽。两种可能性:

  1. 如果您在较旧的操作系统上运行,或者在迫使进程使用有限数量的内存的操作系统上运行,则可能需要增加Python进程可以访问的内存数量。
  2. 使用分块将列表分开。例如,执行列表的前1000个元素,腌制并将其保存到磁盘,然后再进行下1000个。要使用它们,请一次释放一个块,以免耗尽内存。从本质上讲,这与数据库用于处理超过RAM中容纳的更多数据的技术相同。

因此,在32位系统上,python列表的最大大小为536,870,912个元素。Okey,但就我而言,我还没有这个值,在此进程中,我的内存仅为〜1.3 Gb(接近python32进程的限制吗?)。python64的限制是多少?分块将如何减慢我的马尔可夫链演练?感谢@所有人的回答和建议。学习的好地方!
陶波2011年

2
一个32位进程在理论上限制为4 GB的内存,尽管如果您的操作系统也是32位,则显然会更少,因为操作系统将占用部分内存。分块处理会降低您的速度,但是在某些情况下,您必须接受速度降低才能完成处理。您在该列表中存储了什么?也许这将有助于解释发生了什么。
G Gordon Worley III

28

MemoryError您看到的异常是可用RAM耗尽的直接结果。这可能是由于Windows(32位程序)对每个程序施加了2GB的限制,或者计算机上没有可用的RAM。(此链接是上一个问题)。

如果您使用的是Windows的64位副本,那么您应该能够使用Python的64位副本扩展2GB。

IndexError可能是因为PythonMemoryError 在计算整个数组之前命中了异常。同样,这是一个内存问题。

为了解决这个问题,您可以尝试使用64位的Python副本,或者更好地找到一种将结果写入文件的方法。为此,请看numpy的内存映射数组

您应该能够将整个计算集运行到这些数组之一中,因为实际数据将写入磁盘,并且只有一小部分存储在内存中。


1
你好,托马斯,我想你是对的,我必须在Windows-7-64b上将python32所强加的每个程序2GB溢出。python64程序的限制是什么?谢谢
陶波

因为要通过移动到64位来平方地址空间的大小,所以它远远多于计算机中的物理内存:)
ncoghlan 2011年

@ncoghlan是正确的。如果您点击第二行中的链接,则会提及限制。高达8TB。如果您达到该限制,那么您肯定做错了:)
thomas

8

Python没有施加内存限制。但是,MemoryError如果RAM用完,您将得到一个。您说您的中有20301个元素list。对于似乎简单的数据类型(例如int)来说,这似乎太小而不会导致内存错误,但是如果每个元素本身都是一个占用大量内存的对象,则很可能内存不足。

IndexError然而,可能是造成因为你ListTemp已经得到了只有19767元(索引0到19766),和你想过去的最后一个元素的访问。

在不确切知道您要做什么的情况下很难说可以避免达到极限的方法。使用numpy可能会有所帮助。看起来您正在存储大量数据。可能您不需要在每个阶段都存储所有内容。但是,不知道是不可能说的。


2
像任何其他程序一样,Python使用整个虚拟内存,而不仅仅是物理(RAM)。发布者可以增加可用的交换内存(在Windows中是文件,在Linux中是分区)。
里卡多·克鲁兹

2
您也可以在Linux上使用交换文件。摘自Arch Wiki:# touch /swapfile # fallocate -l 512M /swapfile # dd if=/dev/zero of=/swapfile bs=1M count=512 # chmod 600 /swapfile # mkswap /swapfile # swapon /swapfile # echo "/swapfile none swap defaults 0 0" >> /etc/fstab
copeland3300'9

0

如果您想解决此问题,也可以使用货架。然后,您将创建与机器可以处理的容量大小相同的文件,并且仅在必要时才将它们放到RAM中,基本上是写入HD并将信息分段拉回以便可以对其进行处理。

创建二进制文件并检查是否已包含信息(如果是),请创建一个局部变量以保存该文件,否则编写一些您认为必要的数据。

Data = shelve.open('File01')
   for i in range(0,100):
     Matrix_Shelve = 'Matrix' + str(i)
     if Matrix_Shelve in Data:
        Matrix_local = Data[Matrix_Shelve]
     else:
        Data[Matrix_Selve] = 'somenthingforlater'

希望它听起来不太古怪。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.