【问题标题】:Generating very large 2D-array in Python?在 Python 中生成非常大的二维数组?
【发布时间】:2014-06-27 15:25:27
【问题描述】:

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

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

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,甚至开始分配到交换区?

【问题讨论】:

    标签: python arrays matrix byte ram


    【解决方案1】:

    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 位机器中不会导致碎片问题,但分配大块数据仍然容易得多。

    如果您有很多可以放入数组的数据,那么您需要有充分的理由不使用numpy

    【讨论】:

    • 在这里 numpy 上 +1。另外,scipy-lecture 注释中对数组进行了精彩的讨论。很优雅。
    猜你喜欢
    • 2014-08-20
    • 2019-01-30
    • 2021-12-15
    • 1970-01-01
    • 1970-01-01
    • 2011-03-04
    • 2010-09-08
    • 2011-07-23
    • 2021-01-16
    相关资源
    最近更新 更多