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

时间:2019-08-15 09:48:35

标签: python numpy data-science

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

8 个答案:

答案 0 :(得分:37)

这可能是由于系统的overcommit handling模式造成的。

在默认模式下,var zipCode=[...]; //zipCode is array of zip codes. function func1() { zipCode.forEach((item, index) => { drawZipCodeMarker(item.zip); }); } function drawZipCodeMarker(zip){ geocoder.geocode({'address':zip}, (results, status) => { console.log(zip); console.log(results); if (results != null) { var temp = new google.maps.Marker({position : results[0].geometry.location, map:map, title:zip}); } }); }

  

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

这里使用的确切启发式方法并没有得到很好的解释,但这在Linux over commit heuristicon this page上有更多讨论。

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

0

在这种情况下,您要分配

$ cat /proc/sys/vm/overcommit_memory
0

〜282 GB,并且内核显然说得很好,我无法将这么多物理页提交给它,并且它拒绝分配。

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

>>> 156816 * 36 * 53806 / 1024.0**3
282.8939827680588

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

我自己在具有32 GB RAM的计算机上对此进行了测试。使用过量提交模式$ echo 1 > /proc/sys/vm/overcommit_memory ,我也得到了一个0,但是将其更改回MemoryError后,它可以正常工作:

1

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

答案 1 :(得分:4)

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

Windows 8

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

Windows 10

  1. 按Windows键
  2. 键入SystemPropertiesAdvanced
  3. 点击以管理员身份运行
  4. 点击设置
  5. 选择“高级”标签
  6. 选择更改...
  7. 取消选中“自动管理所有驱动器的页面文件大小”
  8. 然后选择“自定义尺寸”并填写适当的尺寸
  9. 按Set,然后按OK,然后退出“虚拟内存”,“性能选项”和“系统属性”对话框
  10. 重新启动系统

注意:在此示例中,我的系统上没有足够的内存来容纳〜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中的不稳定和崩溃。但是,硬盘驱动器的读/写时间比数据存储在计算机内存中的速度要慢得多。页面文件较大将增加硬盘驱动器的工作量,从而导致其他所有文件的运行速度变慢。仅当遇到内存不足错误时才应增加页面文件的大小,并且仅作为临时解决方案。更好的解决方案是向计算机添加更多内存。

答案 2 :(得分:3)

在我的情况下,添加dtype属性会将数组的dtype更改为较小的类型(从float64更改为uint8),减小数组的大小以至于不会在Windows(64位)中引发MemoryError。

来自

mask = np.zeros(edges.shape)

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

答案 3 :(得分:1)

在Windows上也可以解决此问题。对我来说,问题是我使用的是32位版本的Python,而不是64位版本。 32位计算机的进程限制为2 ^ 32 = 4 GB。因此32位版本无法利用我的32GB RAM。

使用 64位版本的Python ,一切正常。

注释1 :您可以在输入解释器时检查您使用的版本。我具有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。

注释2 :截至撰写本文时(2019年11月),matplotlib在python39上为not available,所以我建议安装64位python37

来源:

答案 4 :(得分:1)

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

答案 5 :(得分:1)

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

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

答案 6 :(得分:0)

我尝试了以上所有方法,但没有任何效果。目前,我正在创建50,000个数据框的样本。 (60,000给出了相同的错误)

df = df.sample(50000, replace=True)

答案 7 :(得分:0)

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