What's the maximum size of a numpy array?
我正在尝试创建一个包含2708000000元素的矩阵。 当我尝试创建此大小的numpy数组时,它给了我一个值错误。 有什么办法可以增加最大数组大小?
a = np.arange(2708000000)
ValueError跟踪(最近一次通话)
ValueError:超出最大允许大小
您正在尝试创建一个包含27亿个条目的数组。如果您运行的是64位numpy,则每条记录占用8个字节,则总计为20 GB。
因此几乎可以肯定,您的计算机内存不足。 numpy中没有一般的最大数组大小。
ValueError指示该大小太大而无法分配,而不是没有足够的内存。在我的笔记本电脑上,使用64位python,如果我减少位数,则可以分配它:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | In [16]: a=np.arange(2708000000) --------------------------------------------------------------------------- MemoryError Traceback (most recent call last) <ipython-input-16-aaa1699e97c5> in <module>() ----> 1 a=np.arange(2708000000) MemoryError: # Note I don't get a ValueError In [17]: a = np.arange(2708000000, dtype=np.int8) In [18]: a.nbytes Out[18]: 2708000000 In [19]: a.nbytes * 1e-6 Out[19]: 2708.0 |
在您的情况下,arange使用
根本原因是用于访问数据的指针的大小以及用这些位可以表示多少个数字:
1 2 3 4 | In [26]: np.iinfo(np.int32) Out[26]: iinfo(min=-2147483648, max=2147483647, dtype=int32) In [27]: np.iinfo(np.int64) Out[27]: iinfo(min=-9223372036854775808, max=9223372036854775807, dtype=int64) |
请注意,如果尝试创建一个非常大的数组,我可以复制您的ValueError:
1 2 3 4 5 6 7 | In [29]: a = np.arange(1e350) --------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-29-230a6916f777> in <module>() ----> 1 a = np.arange(1e350) ValueError: Maximum allowed size exceeded |
如您所说,如果您的计算机有很多内存,它将是64位,因此您应该安装Python 64位才能访问它。另一方面,对于如此大的数据集,您应考虑使用核心外计算的可能性。
我能够创建一个大小为60亿的数组,占用了45GB的内存。默认情况下,numpy创建了一个类型为float64的数组。通过降低精度,我可以节省很多内存。
1 2 3 | np.arange(6000000000,dtype=np.dtype('f8')) np.arange(6000000000,dtype=np.dtype('f4')) #etc... |
默认== float64
-
np.float64-45.7GB
-
np.float32-22.9GB
-
np.int8-5.7GB
显然,一个8位整数不能存储6B的值。我确定某个时候会存在最大大小,但是我怀疑它在2016年可能会超过FAR。有趣的是," Python Blaze"允许您在磁盘上创建numpy数组。我记得前一段时间玩过它,并创建了一个占用1TB磁盘的超大型阵列。
实际上,它与系统最大地址长度有关,简单地说,就是32位系统或64位系统。以下是这些问题的解释,最初是由马克·迪金森(Mark Dickinson)提出的
简短的答案:Python对象开销正在杀死您。在64位计算机上的Python 2.x中,即使在考虑字符串内容之前,字符串列表每个列表项也会消耗48个字节。对于您描述的阵列大小,这超过了8.7 Gb的开销。在32位计算机上会更好一些:每个列表项只有28个字节。
更长的解释:您应该意识到Python对象本身可能非常大:甚至是简单的对象(例如int,float和字符串)。在您的代码中,您最终得到一个字符串列表列表。在我的(64位)计算机上,即使是空字符串对象也占用40个字节,为此,您需要为指向该内存中该字符串对象的列表指针添加8个字节。因此,每个条目已经有48个字节,大约8.7 Gb。鉴于Python一次分配的内存为8字节的倍数,并且您的字符串几乎肯定是非空的,因此实际上您实际上是在每个条目中查看56或64个字节(我不知道您的字符串有多长)。
可能的解决方案:
(1)通过将条目从字符串转换为ints或float可能会做得更好。
(2)通过使用Python的数组类型(与list不同)或使用numpy,您会做得更好:然后,您的int或float只会占用4或8个字节。
从Python 2.6开始,您可以使用sys.getsizeof函数获取有关对象大小的基本信息。请注意,如果将其应用于列表(或其他容器),则返回的大小不包括所包含列表对象的大小。仅用于保存这些对象的结构。这是我机器上的一些值。