无法分配具有形状和数据类型的数组

Posted

技术标签:

【中文标题】无法分配具有形状和数据类型的数组【英文标题】:Unable to allocate array with shape and data type 【发布时间】:2019-12-21 18:52:31 【问题描述】:

我在 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 上也失败了

【问题讨论】:

内存中是否有其他进程在运行? 不,我试过 topfree -m,这些命令可以释放 60gb 的内存等等 + 理论上应该占用 35GB 内存 不太可能,但您不会碰巧在 Ubuntu 中运行 32 位 Python 解释器,对吧? np.zeros 不会创建 sparse 矩阵。填零可能会有延迟。但见***.com/q/27464039 【参考方案1】:

这可能是由于您系统的overcommit handling 模式所致。

在默认模式下,0

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

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

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

$ 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 设置的其他问题。【参考方案2】:

我在 Window 上遇到了同样的问题并遇到了这个解决方案。因此,如果有人在 Windows 中遇到此问题,我的解决方案是增加 pagefile 大小,因为这对我来说也是内存过度使用问题。

Windows 8

    在键盘上按 WindowsKey + X 然后在弹出菜单中单击系统 点击或单击高级系统设置。系统可能会要求您输入管理员密码或确认您的选择 在“高级”选项卡的“性能”下,点按或单击“设置”。 点击或单击“高级”选项卡,然后在“虚拟内存”下点击或单击“更改” 清除“自动管理所有驱动器的页面文件大小”复选框。 在驱动器 [卷标签] 下,点击或单击包含要更改的页面文件的驱动器 点击或单击自定义大小,在初始大小 (MB) 或最大大小 (MB) 框中输入新大小(以兆字节为单位),点击或单击设置,然后点击或单击确定 重启系统

Windows 10

    按 Windows 键 输入 SystemPropertiesAdvanced 点击以管理员身份运行 在性能下,点击设置 选择“高级”选项卡 选择更改... 取消选中自动管理所有驱动器的分页文件大小 然后选择自定义尺寸并填写合适的尺寸 按设置,然后按确定,然后退出虚拟内存、性能选项和系统属性对话框 重启系统

注意:在本例中,我的系统上没有足够的内存来支持 ~282GB,但对于我的特殊情况,这是可行的。

编辑

来自here的页面文件大小建议:

有一个计算正确页面文件大小的公式。初始大小是系统内存总量的一倍半 (1.5) x。最大尺寸为三 (3) x 初始尺寸。因此,假设您有 4 GB(1 GB = 1,024 MB x 4 = 4,096 MB)的内存。初始大小为 1.5 x 4,096 = 6,144 MB,最大大小为 3 x 6,144 = 18,432 MB。

here的一些注意事项:

但是,这并未考虑您的计算机可能特有的其他重要因素和系统设置。同样,让 Windows 选择使用什么,而不是依赖在不同计算机上运行的任意公式。

还有:

增加页面文件大小可能有助于防止 Windows 中的不稳定和崩溃。但是,硬盘驱动器的读/写时间比数据在计算机内存中时要慢得多。拥有较大的页面文件将为您的硬盘增加额外的工作,导致其他一切运行速度变慢。只有在遇到内存不足错误时才应增加页面文件大小,并且只能作为临时修复。更好的解决方案是为计算机添加更多内存。

【讨论】:

您现在有哪些自定义尺寸(初始尺寸 + 最大尺寸)设置?不知道要为自己分配多少 @Azizbro 我现在已经回到默认值,但只是调整了值,直到内存不足错误消失。 我已经这样做了,我仍然得到MemoryError: Unable to allocate 10.3 PiB for an array with shape (38137754, 38137754) and data type float64 这对我有用。但是我们最好不要在系统台(C:) 中分配虚拟内存。否则,重新启动计算机时会很慢。 【别说我怎么知道的,我做到了T.T T.T】 @GeorgeAdams 它也不能在我的机器上运行。我正在使用 vs code 并注意到我必须以管理员身份运行它。这对我有用【参考方案3】:

我在 Windows 上也遇到过这个问题。我的解决方案是从 32 位版本的 Python 切换到 64 位版本的 Python。事实上,32 位软件,如 32 位 CPU,可以寻址maximum of 4 GB 的 RAM (2^32)。因此,如果您的 RAM 超过 4 GB,则 32 位版本无法利用它。

使用 64 位版本的 Python(下载页面中标记为 x86-64 的版本),问题就消失了。

您可以通过输入解释器来检查您拥有的版本。我,使用 64 位版本,现在有: Python 3.7.5rc1 (tags/v3.7.5rc1:4082f600a5, Oct 1 2019, 20:28:14) [MSC v.1916 64 bit (AMD64)],其中 [MSC v.1916 64 位 (AMD64)] 表示“64 位 Python”。

来源:

Quora - memory error generated by large numpy array

*** : 32 or 64-bit version of Python

【讨论】:

如何进入解释器? 也解决了我的问题。使用 Pycharm。卸载32位版本,重新安装64位版本,将项目解释器更改为新的64位python。 @Shayan :要进入解释器,打开终端(Win + Rcmd)并输入python -i 我已经Python 3.7.6 (default, Jan 8 2020, 20:23:39) [MSC v.1916 64 bit (AMD64)] :: Anaconda, Inc. on win32。我的计算总内存为 16GM,可用内存为 4.4 GM,但我仍然有问题。【参考方案4】:

有时,由于内核已达到其限制,会弹出此错误。尝试重启内核重做必要的步骤。

【讨论】:

请参考:***.com/help/how-to-answer 不错的尝试。 请详细说明你的答案 它确实发生在我身上。尝试使用手动垃圾收集器。【参考方案5】:

在我的例子中,添加 dtype 属性将数组的 dtype 更改为更小的类型(从 float64 到 uint8),将数组大小减小到足以不会在 Windows(64 位)中引发 MemoryError。

来自

mask = np.zeros(edges.shape)

mask = np.zeros(edges.shape,dtype='uint8')

【讨论】:

【参考方案6】:

将数据类型更改为另一种使用较少内存的工作。对我来说,我将数据类型更改为 numpy.uint8:

data['label'] = data['label'].astype(np.uint8)

【讨论】:

【参考方案7】:

我有同样的问题 但原因很简单 错误的十进制分隔符设置“,”而不是“。” 享受

【讨论】:

请详细说明您的答案。

以上是关于无法分配具有形状和数据类型的数组的主要内容,如果未能解决你的问题,请参考以下文章

MemoryError:无法为形状(725000、277、76)和数据类型 float64 的数组分配 30.4 GiB

数组

复杂数据类型的机器级表示

java分配内存空间

无法将类型 [NSObject] 的值分配给类型 NSObject

数组和函数方法