我在 Ubuntu 18 上在 numpy 中分配巨大的数组时遇到了问题,而在 MacOS 上却没有遇到同样的问题。
我正在尝试为形状为 (156816, 36, 53806)
的 numpy 数组分配内存
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 上也失败了
原文由 Martin Brisiak 发布,翻译遵循 CC BY-SA 4.0 许可协议
这可能是由于您的系统的 过度使用处理 模式。
在默认模式下,
0
,这里没有很好地解释所使用的确切启发式,但在 Linux over commit heuristic 和 此页面上对此 进行了更多讨论。
您可以通过运行检查当前的过度使用模式
在这种情况下,您正在分配
~282 GB,内核说得很好,显然我不可能向它提交那么多物理页面,它拒绝分配。
如果(以 root 身份)您运行:
这将启用“始终过度使用”模式,并且您会发现系统确实允许您进行分配,无论它有多大(至少在 64 位内存寻址范围内)。
我自己在具有 32 GB RAM 的机器上进行了测试。使用过度使用模式
0
我也得到了一个MemoryError
,但是在将它改回1
后它可以工作:然后,您可以继续写入阵列中的任何位置,系统只会在您明确写入该页面时分配物理页面。因此,您可以小心地将其用于稀疏数组。