我在 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 上也失败了
这可能是由于你系统的过量使用处理模式造成的。
在默认模式下0
,
启发式过量使用处理。明显的地址空间过度使用被拒绝。用于典型系统。它确保严重的疯狂分配失败,同时允许过度使用以减少交换使用。在这种模式下,允许根分配更多的内存。这是默认设置。
此处没有很好地解释所使用的确切启发式方法,但在Linux 上通过提交启发式方法和此页面上对此进行了更多讨论 。
你可以通过运行来检查当前的过量使用模式
$ 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 的机器上对此进行了测试。在过量使用模式下,0
我也得到了一个MemoryError
,但在将其改回后1
可以工作:
>>> import numpy as np
>>> a = np.zeros((156816, 36, 53806), dtype='uint8')
>>> a.nbytes
303755101056
然后,你可以继续写入阵列中的任何位置,系统只会在你明确写入该页面时分配物理页面。所以你可以小心地将它用于稀疏数组。
这是 Linux 内核的一项特殊功能,因此在 MacOS 上不一定有直接的等价物,尽管可能有类似的东西。我认为在 Mac 上修改内核设置并不容易。
@Iguananaut“小心”警告的确切含义是什么?IE。在带有 GTX 1080 GPU 的 Ubuntu 18 服务器上出现问题的最坏情况是什么?
@mLstudent33 首先,这与您的 GPU 无关,它有自己的内存。我的意思是你仍然可以填满你的内存——每次你写入内存中的某个页面时,该页面(通常是 4k 字节)必须提交到物理内存。所以最坏的情况是你的内存不足。
此更改是立即生效还是我们需要重新启动我们的 shell 或机器本身?
它立即生效,但如果没有其他措施,它不会在重新启动后持续存在。搜索有关如何最好地
/proc/sys
在您的发行版上保留设置的其他问题。