首页 > 解决方案 > 无法分配具有形状和数据类型的数组

问题描述

我在 Ubuntu 18 上在 numpy 中分配巨大的数组时遇到了问题,而在 MacOS 上却没有遇到同样的问题。

我正在尝试为形状为的 numpy 数组分配(156816, 36, 53806) 内存

np.zeros((156816, 36, 53806), dtype='uint8')

当我在 Ubuntu 操作系统上遇到错误时

>>> import numpy as np
>>> np.zeros((156816, 36, 53806), dtype='uint8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
numpy.core._exceptions.MemoryError: Unable to allocate array with shape (156816, 36, 53806) and data type uint8

我没有在 MacOS 上得到它:

>>> import numpy as np 
>>> np.zeros((156816, 36, 53806), dtype='uint8')
array([[[0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        ...,
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0]],

       [[0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        ...,
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0]],

       [[0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        ...,
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0]],

       ...,

       [[0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        ...,
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0]],

       [[0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        ...,
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0]],

       [[0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        ...,
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0]]], dtype=uint8)

我读过某处np.zeros不应该真正分配数组所需的整个内存,而只是分配非零元素的地方。尽管 Ubuntu 机器有 64gb 的内存,而我的 MacBook Pro 只有 16gb。

版本:

Ubuntu
os -> ubuntu mate 18
python -> 3.6.8
numpy -> 1.17.0

mac
os -> 10.14.6
python -> 3.6.4
numpy -> 1.17.0

PS:在 Google Colab 上也失败了

标签: pythonnumpydata-science

解决方案


这可能是由于您的系统的过度使用处理模式。

在默认模式下,0,

启发式过度使用处理。明显的地址空间过度使用被拒绝。用于典型系统。它确保严重的疯狂分配失败,同时允许过度使用以减少交换使用。在这种模式下,root 可以分配稍微多一点的内存。这是默认设置。

这里没有很好地解释所使用的确切启发式,但在 Linux over commit heuristic此页面上对此进行了更多讨论。

您可以通过运行检查当前的过度使用模式

$ cat /proc/sys/vm/overcommit_memory
0

在这种情况下,您正在分配

>>> 156816 * 36 * 53806 / 1024.0**3
282.8939827680588

~282 GB,内核说得很好,显然我不可能向它提交那么多物理页面,它拒绝分配。

如果(以 root 身份)您运行:

$ echo 1 > /proc/sys/vm/overcommit_memory

这将启用“始终过度使用”模式,您会发现系统确实允许您进行分配,无论它有多大(至少在 64 位内存寻址范围内)。

我自己在具有 32 GB RAM 的机器上进行了测试。使用 overcommit 模式0我也得到了一个MemoryError,但是在将它改回1它之后可以工作:

>>> import numpy as np
>>> a = np.zeros((156816, 36, 53806), dtype='uint8')
>>> a.nbytes
303755101056

然后,您可以继续写入阵列中的任何位置,系统只会在您明确写入该页面时分配物理页面。因此,您可以小心地将其用于稀疏数组。


推荐阅读