内存错误和列表限制?

69

为了科学目的,我需要生成大型矩阵(马尔可夫链)。我进行计算并将其放入一个由20301个元素组成的列表中(=我的矩阵的一行)。我需要所有这些数据在内存中以进行下一个马尔可夫步骤,但如果需要,我可以将它们存储在别处(例如文件),即使这会减慢我的马尔可夫链遍历速度。我的计算机(科学实验室)配置为:Bi-xenon 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安装程序。请确认您是否使用了64位的Python版本。注意,32位的Python版本最多只能使用4GB的内存。 - mgoldwasser
又大又多!哇!太好了,你有这么多的内存! - Michael Scheper
4个回答

59

首先,请参阅Python数组可以有多大?Numpy中的数组长度问题

其次,唯一的限制来自你拥有的内存量以及系统如何存储内存引用。没有每个列表的限制,因此Python会一直执行,直到内存用尽。 有两种可能性:

  1. 如果您在较旧的操作系统上运行或使用强制进程使用有限内存量的操作系统,则可能需要增加Python进程可访问的内存量。
  2. 使用分块将列表分开。例如,对列表的前1000个元素进行处理,将它们pickle并保存到磁盘中,然后再处理接下来的1000个元素。为了使用它们,逐个取消pickle块,以避免耗尽内存。这本质上是数据库用于处理超出RAM容量的更多数据的相同技术。

因此,在32位系统上Python列表的最大大小为536,870,912个元素。好的,但在我的情况下,我远远达不到这个值,我的内存只有约1.3 Gb(接近Python32进程的限制?)。在Python64中的限制将是什么?分块会如何减慢我的马尔可夫链遍历?感谢所有人的答案和建议。学习的好地方! - Taupi
2
一个32位进程理论上可以使用4GB的内存,但如果你的操作系统也是32位的话,实际可用内存会更少,因为操作系统会占用一部分内存。分块会减慢处理速度,但在某些情况下,你必须接受减速以完成处理。你在列表中存储了什么?也许这可以帮助解释发生了什么。 - Gordon Seidoh Worley

30
你看到的MemoryError异常是RAM不足的直接结果。这可能是由于Windows(32位程序)强制实施的每个程序2GB限制,或者计算机上可用RAM不足引起的。(此link为以前的问题)
如果您使用的是64位Windows版本,则应该能够通过使用64位Python副本来扩展2GB。 IndexError将在Python计算整个数组之前触发MemoryError异常。同样,这是一个内存问题。
为了解决这个问题,您可以尝试使用64位Python副本,或者最好找到一种将结果写入文件的方法。为此,请查看numpy的memory mapped arrays
您应该能够将整个计算集运行到其中一个这些数组中,因为实际数据将被写入磁盘,仅将其保留在内存中的一小部分。

1
你好Thomas,我认为你是正确的,我必须突破我的python32在我的windows-7-64b上强制实施的每个程序2GB的限制。Python64程序的限制将是多少?谢谢。 - Taupi
由于您将地址空间移动到64位,因此比您机器中的物理内存要多得多 :) - ncoghlan
@ncoghlan是正确的。如果您按照第二行中的链接,限制就会被提到。这个限制高达8TB。如果您达到了这个限制,那么肯定是做错了什么 :) - thomas

8
Python没有内存限制,但是如果你的RAM用尽了,就会出现MemoryError。你说你的list中有20301个元素,对于简单数据类型(例如int),这似乎太小了,不会导致内存错误,但如果每个元素本身都是占用大量内存的对象,那么你很可能会耗尽内存。
而IndexError可能是因为你的ListTemp只有19767个元素(索引从0到19766),而你正在尝试访问超过最后一个元素的位置。
不知道你具体要做什么,很难说如何避免达到极限。使用numpy可能有所帮助。看起来你正在存储大量数据,也许你不需要在每个阶段都存储所有数据。但是不知道具体情况,无法确定。

2
Python,像其他程序一样,使用整个虚拟内存,而不仅仅是物理内存(RAM)。用户可以增加可用的交换空间(在Windows中是文件,在Linux中是分区)。 - Ricardo Magalhães Cruz
3
在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

0
如果您想避免这个问题,您也可以使用 shelve。然后,您将创建文件,其大小与您的机器处理能力相同,并且仅在必要时将它们放入 RAM 中,基本上是写入硬盘并分段提取信息以便进行处理。
创建二进制文件并检查其中是否已经存在信息,如果是,则创建一个本地变量来保存它,否则写入一些您认为必要的数据。
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'

希望它听起来不太过时。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接