无法分配具有形状和数据类型的数组
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 上也失败了
【问题讨论】:
内存中是否有其他进程在运行? 不,我试过top
和 free -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 + R
cmd
)并输入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