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

Mar*_*iak 21 python numpy data-science

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

我想一个numpy的阵列形状分配内存(156816, 36, 53806) 使用

np.zeros((156816, 36, 53806), dtype='uint8')
Run Code Online (Sandbox Code Playgroud)

当我在Ubuntu OS上遇到错误时

>>> 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
Run Code Online (Sandbox Code Playgroud)

我在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)
Run Code Online (Sandbox Code Playgroud)

我读过某处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
Run Code Online (Sandbox Code Playgroud)

PS:在Google Colab上也失败

rec*_*for 80

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

视窗 8

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

视窗 10

  1. 按 Windows 键
  2. 类型 SystemPropertiesAdvanced
  3. 点击以管理员身份运行
  4. 在性能下,单击设置
  5. 选择高级选项卡
  6. 选择更改...
  7. 取消选中自动管理所有驱动器的分页文件大小
  8. 然后选择Custom size并填写合适的尺寸
  9. 按 Set 然后按 OK 然后退出 Virtual Memory、Performance Options 和 System Properties 对话框
  10. 重新启动系统

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

编辑

这里对页面文件大小的建议建议:

有一个计算正确页面文件大小的公式。初始大小是系统总内存量的二分之一 (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。

这里要记住的一些事情:

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

还:

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

  • @Azizbro 我现在已经回到默认值,但只是调整了值,直到内存不足错误消失。 (2认同)
  • 我已经这样做了,但仍然得到``MemoryError: Unable to allocate 10.3 PiB for an array with shape (38137754, 38137754) and data type float64```` (2认同)

Igu*_*aut 34

这可能是由于系统的过量使用处理模式所致。

在默认模式下0

启发式过量使用处理。明显的地址空间过量使用被拒绝。用于典型的系统。它确保严重的野生分配失败,同时允许过量使用以减少交换使用。在此模式下,允许root分配更多的内存。这是默认值。

此处没有很好地解释所使用的确切启发式方法,但是在Linux上的提交启发式方法本页上对此进行了更多讨论 。

您可以通过运行以下命令检查当前的过量使用模式

$ cat /proc/sys/vm/overcommit_memory
0
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您要分配

>>> 156816 * 36 * 53806 / 1024.0**3
282.8939827680588
Run Code Online (Sandbox Code Playgroud)

约282 GB,并且内核说的很清楚,我无法将这么多物理页提交给它,并且它拒绝分配。

如果(以root用户身份)运行:

$ echo 1 > /proc/sys/vm/overcommit_memory
Run Code Online (Sandbox Code Playgroud)

这将启用“始终过量使用”模式,并且您会发现,无论系统有多大(至少在64位内存寻址内),系统都可以进行分配。

我自己在具有32 GB RAM的计算机上进行了测试。在过量提交模式下,0我还得到了一个MemoryError,但是将其更改回1它可以工作:

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

然后,您可以继续写入数组中的任何位置,并且只有在您明确写入物理页面时,系统才会分配物理页面。因此,您可以谨慎地将其用于稀疏数组。

  • @Iguananaut “小心”警告的确切含义是什么?IE。在配备 GTX 1080 GPU 的 Ubuntu 18 服务器上出现问题的最坏情况是什么? (3认同)
  • 它立即生效,但如果不采取其他措施,重启后不会持续存在。搜索有关如何最好地在您的发行版上保留“/proc/sys”设置的其他问题。 (3认同)
  • 这是 Linux 内核特有的一个功能,因此 MacOS 上不一定有直接等效的功能,尽管可能有类似的功能。我认为在 Mac 上调整内核设置并不那么容易。 (2认同)
  • 此更改是否立即生效,还是需要重新启动 shell 或机器本身? (2认同)

kot*_*ane 32

我在 Windows 上也遇到了这个问题。我的解决方案是从 32 位切换到 64 位版本的 Python。事实上,32 位软件,如 32 位 CPU,最多可以处理 4 GB的 RAM (2^32)。因此,如果您拥有超过 4 GB 的 RAM,则 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”。

来源:

  • 我已经有了“Python 3.7.6(默认,2020 年 1 月 8 日,20:23:39)[MSC v.1916 64 位(AMD64)]:: Anaconda, Inc. on win32”。我的计算总体内存为 16GM,可用内存为 4.4GM,但我仍然遇到问题。 (7认同)
  • 如何输入口译员? (3认同)
  • 也解决了我的问题。使用Pycharm。卸载32位版本,重新安装64位版本,将项目解释器更改为新的64位python。 (2认同)
  • @Shayan:要进入解释器,请打开终端(“Win + R”“cmd”)并输入“python -i”。 (2认同)

小智 5

在我的情况下,添加 dtype 属性将数组的 dtype 更改为较小的类型(从 float64 到 uint8),减少数组大小足以在 Windows(64 位)中不抛出 MemoryError。

mask = np.zeros(edges.shape)
Run Code Online (Sandbox Code Playgroud)

mask = np.zeros(edges.shape,dtype='uint8')
Run Code Online (Sandbox Code Playgroud)


小智 5

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

data['label'] = data['label'].astype(np.uint8)
Run Code Online (Sandbox Code Playgroud)