我在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上也失败
答案 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 heuristic和on 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
Windows 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)
我遇到了同样的问题 但原因很简单 错误的十进制分隔符设置“,”而不是“。” 享受