Python大型列表的内存需求是多少?

5

我正在做一些愚蠢的事情,比如:

from itertools import *
rows = combinations(range(0, 1140), 17)
all_rows = []
for row in rows:
    all_rows.append(row)

毫不意外,我用完了内存地址空间(32位Python 3.1)。我的问题是:如何计算我需要多少内存地址空间来存储一个大型列表?在这种情况下,列表的大小约为2.3X10^37。Python中是否有一个函数可以返回我要查找的信息,或者实际上是一个较小但类似的列表的大小?有哪些工具可用?


3
10^37?真的吗?这大约是125位的寻址空间,仅用于计算元素的数量。你需要从根本上重新考虑这个问题。存储并不是真正的问题所在。你需要做一些事情来避免枚举所有可能的组合方式。 - S.Lott
1
顺便提一下,64位只能计数到10的19次方。 - S.Lott
4
文森特的问题清楚地表明他知道这是“愚蠢的”,而他真正关心的是如何计算内存消耗,具体来说有哪些工具可用。那是一个完全合法、表述清晰的问题。 - Peter Hansen
@Peter Hansen:对问题的阅读很有意思。我认为这是对正在发生的事情重要性的一种无法理解的失败。"内存不足"只是一个非常真实问题的症状。根本问题在于没有考虑到这种方法的巨大规模。即使每个项目只占用一个位,这种方法也是不可行的,所以内存使用的答案是无关紧要的。 - S.Lott
@ Peter Hanson,我确实希望能够做到这一点,但更重要的是我想了解在内存上下文中此类事物的限制。 @S.Lott,我确定我已经用完了,或者更正确地说,这是我得到的错误。 而不是找到0-1140个整数的组合,我实际上有1140个长度为17的列表。但我收到了相同的错误。 - Vincent
显示剩余7条评论
4个回答

11

Python 2.6版本开始,有一个方便的函数sys.getsizeof(),它能帮助解决这个问题:

>>> import sys
>>> sys.getsizeof(1)  # integer
12
>>> sys.getsizeof([]) # empty list
36
>>> sys.getsizeof(()) # empty tuple
28
>>> sys.getsizeof((1,))  # tuple with one element
32

从这里可以看出,每个整数占用12个字节,而列表或元组中每个引用的内存为4个字节(在32位机器上),加上开销(分别为36或28个字节)。

如果你的结果是由长度为17的整数元组组成的,那么每个元组将占用300个字节:17*(12+4)+28。结果本身是一个列表,因此每个引用需要36个字节加上4个字节。找出列表的长度(称之为N),则总共需要的字节数为:36+N*(4+300)

编辑:还有一件事情可能会显著影响结果。Python会根据需要为大多数整数值创建新的整数对象,但对于小的整数(经验确定为Python 2.6.4在Windows上的范围[-5,256]),它会预先创建它们并重复使用它们。如果你的值中有很大一部分小于257,这将显著减少内存消耗。(在Python中,257不等于257+0 ;-)).


请注意,Slide Inc 新开源了一个软件包:http://github.com/slideinc/meminfo,它是一个“用于查找 Python 对象精确内存大小的 C 扩展”。 - Peter Hansen
请注意,sys.getsizeof() 不受 PyPy 支持。 - amcnabb

4

首先,不要写成:

all_rows = []
for row in rows:
    all_rows.append(row)

您可以简单地编写以下代码:
all_rows = list(rows)

这将会更加高效。

接下来,有两个方面需要考虑列表的内存消耗:

  • 列表中包含的对象的内存消耗;这显然取决于这些对象、它们的类型以及是否存在大量共享
  • 列表本身的内存消耗;列表中的每个对象都由一个指针引用,32位模式下占用4个字节,64位模式下占用8个字节;因此,粗略地说,列表本身的大小是(4或8个字节)乘以列表中的对象数量(这忽略了固定列表头部开销和Python列表进行适度过分配的相对较少的开销)

顺便提一下,在最近的Python版本中,您可以使用sys.getsizeof()来获取对象的大小:

>>> import sys
>>> sys.getsizeof([None] * 100)
872

3
补充说明:由于您正在处理整数列表并担心内存使用问题,因此还有一个array模块可供使用:

[array]定义了一种对象类型,可以紧凑地表示基本值的数组:字符、整数、浮点数。数组是序列类型,行为非常类似于列表,只是存储在其中的对象类型受到限制。该类型在对象创建时指定[...]。


1

这是一个NP完全问题,但我主要是想学习一些知识,或许能够偶然找到答案。问题在这里陈述: http://blog.computationalcomplexity.org/2009/11/17x17-challenge-worth-28900-this-is-not.html - Vincent
我想要实际组合的列表,我知道有多少个。 - Vincent

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