在Python中生成非常大的2D数组?

时间:2014-06-27 15:25:27

标签: python arrays matrix byte ram

我想使用列表列表生成非常大的2D数组(或者,换句话说,矩阵)。每个元素都应该是一个浮点数。

所以,举一个例子,让我们假设有以下代码:

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已经满了。现在,如果我没错,每个浮点数都是64位大(或8字节),因此占用的总RAM应为:

32000 * 32000 * 8 / 1 MB = 8192 MB

为什么python会填满我的整个RAM,甚至开始分配到swap?

1 个答案:

答案 0 :(得分:3)

Python不一定以最紧凑的形式存储列表项,因为列表需要指向下一项的指针等。这是一种允许删除,插入等数据类型的副作用。对于简单的两个 - 方式链表列表的用法是两个指针加上值,在64位机器中,列表中每个浮点项目为24个八位字节。在实践中,实现并不是那么愚蠢,但仍然存在一些开销。

如果您想要一个简洁的格式,我建议使用numpy.array,因为它会花费您认为它所需的字节数(加上一小部分开销)。

修改糟糕。不必要。解释错误,建议有效。由于这个原因,numpynumpy.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

(字节数不完全可靠,因为对象本身需要一些空间用于元数据等。必须有指向内存块开头,数据类型,数组形状等的指针)。 p>

这花费的时间少得多。阵列的创建几乎是即时的,插入数字可能需要一两秒钟。分配和释放大量小内存块非常耗时,虽然它不会在64位计算机中造成碎片问题,但分配大量数据仍然要容易得多。

如果您有大量可以放入数组的数据,则需要一个不使用numpy的充分理由。