我想使用列表列表生成非常大的二维数组(或者,换句话说,矩阵)。每个元素都应该是一个 float 。
因此,仅举一个例子,我们假设有以下代码:
import numpy as np
N = 32000
def largeMat():
m = []
for i in range(N):
l = list(np.ones(N))
m.append(l)
if i % 1000 == 0:
print i
return m
m = largeMat()
我有 12GB RAM,但是当代码到达矩阵的第 10000 行时,我的 RAM 已经满了。现在,如果我没记错的话,每个 float 都是 64 位大(或 8 字节),所以总占用的 RAM 应该是:
32000 * 32000 * 8 / 1 MB = 8192 MB
为什么 python 会填满我的整个 RAM,甚至开始分配到交换区?
最佳答案
Python 不一定以最紧凑的形式存储列表项,因为列表需要指向下一项的指针等。这是拥有允许删除、插入等的数据类型的副作用。对于简单的两个 -链接列表的用法是两个指针加上值,在 64 位机器中,列表中的每个浮点项有 24 个八位字节。在实践中,实现并没有那么愚蠢,但仍然存在一些开销。
如果您想要简洁的格式,我建议使用 numpy.array
因为它会占用您认为需要的字节数(加上一点点开销)。
编辑哎呀。不必要。解释错误,建议有效。 numpy
是正确的工具,因为 numpy.array
正是出于这个原因而存在。然而,问题很可能是其他的。即使需要很长时间(大约 2 分钟),我的计算机也会运行该过程。另外,在此之后退出 python 需要很长时间(实际上,它挂起了)。 python 进程的内存使用量(如 top
报告)峰值为 10 000 MB,然后下降到略低于 9 000 MB。分配的 numpy 数组可能不会很快被垃圾收集。
但是关于我的机器中的原始数据大小:
>>> import sys
>>> l = [0.0] * 1000000
>>> sys.getsizeof(l)
8000072
因此,每个列表似乎有 72 个八位字节的固定开销。
>>> listoflists = [ [1.0*i] * 1000000 for i in range(1000)]
>>> sys.getsizeof(listoflists)
9032
>>> sum([sys.getsizeof(l) for l in listoflists])
8000072000
所以,这符合预期。
另一方面,保留和填充长列表需要一段时间(大约 10 秒)。另外,退出 python 需要一段时间。 numpy 也是如此:
>>> a = numpy.empty((1000,1000000))
>>> a[:] = 1.0
>>> a.nbytes
8000000000
(字节数并不完全可靠,因为对象本身需要一些空间用于其元数据等。必须有指向内存块开头的指针、数据类型、数组形状等)
这需要更少的时间。数组的创建几乎是瞬时的,插入数字可能需要一两秒。分配和释放大量小内存块非常耗时,虽然在 64 位机器中不会导致碎片问题,但分配大数据 block 仍然要容易得多。
如果您有大量可以放入数组的数据,那么您需要一个不使用numpy
的充分理由。
关于python - 在Python中生成非常大的二维数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24455445/