我想构建一个numpy数组但是我在拥有16 GB RAM的Windows中得到了MemoryError。要提供更多信息,详情如下:
Python 2.7.13 |Anaconda custom (64-bit)| (default, May 11 2017, 13:17:26) [MSCv.1500 64 bit (AMD64)] on win32
xx = np.zeros((110000,80000,3))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
MemoryError
然而,完全相同的代码在具有8 GB RAM的mac计算机上运行。详情如下:
Python 2.7.12 |Anaconda 4.2.0 (x86_64) [GCC 4.2.1 (LLVM build ... )on darwin)]
xx = np.zeros((1100000,8000000,3)) doesn't give error.
当我最后增加大小时,我在Mac上遇到错误,但错误不同如下:
xx = np.zeros((1100000,80000000,3))
python(713,0x7fffa76b33c0) malloc: *** mach_vm_map(size=211200000000000)
failed (error code=3)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
MemoryError
我怎么能处理这个问题?
答案 0 :(得分:2)
您的阵列太大而无法放入两个系统的物理RAM中:
110000 * 80000 * 3 * 8 / 1024 / 1024 / 1024 = 196.[69] GB
然而,这取决于你的系统如何处理内存请求以及它如何“存储”内存。例如,系统可以简单地为您的进程“保留”内存,但会推迟实际分配,直到读取/修改内存为止。即使分配了内存,也可以压缩内存(如评论中所述,感谢@Martijn Pieters)并且可以很好地压缩大量的零 - 但是只要修改内存,压缩就会降低效率,使用更多“真实记忆”。
这意味着它在失败时由系统决定(如果你真的对数组做了什么,最终都会失败)。当您请求的物理内存超过您的情况时,Windows中的Windows会立即选择失败。在Mac上,似乎你必须修改“足够”的值(参见this answer on "Why a 352GB NumPy ndarray can be used on a 8GB memory macOS computer?"),直到它失败。
import numpy as np
arr = np.zeros((110000,80000,3)) # MemoryError on Windows
arr += 10 # MemoryError on Mac
您可以使用例如psutil
来检查使用的内存量(物理和虚拟):
import psutil
print(psutil.virtual_memory())
# svmem(total=4170924032, available=1666629632, percent=60.0, used=2504294400, free=1666629632)
arr = np.zeros((10000, 10000))
print(psutil.virtual_memory())
# svmem(total=4170924032, available=1664675840, percent=60.1, used=2506248192, free=1664675840)
arr += 10
print(psutil.virtual_memory())
# svmem(total=4170924032, available=864059392, percent=79.3, used=3306864640, free=864059392)
因此,即使在Windows上,np.zeros
也不会立即“使用”物理内存,直到需要它为止。
我怎么能处理这个问题?
最简单(但可能是最昂贵)的选择是购买(大量)更多内存。但您也可以尝试使用适合您物理内存的块大小来“处理”处理。最终,最好的解决方案是重新考虑您的方法/算法,这样您就不需要那么多内存。
答案 1 :(得分:1)
如前所述,您的阵列太大而无法容纳两台计算机上的物理内存。 但重点是物理内存只是现代系统中通常可用的内存的一部分,另一个是虚拟内存。
我不确定NumPy的Windows版本是否实际编译为仅使用物理内存,这可能是,但我发现它不太可能。 因此,您的Mac可以处理该阵列的原因可能是它配置为具有比虚拟内存大得多的虚拟内存(读取 swap )(读取 PageFile )在Windows机器上可用。 因此,增加Windows计算机上的 PageFile 大小可能会解决您的问题。 然而,这远非理想,因为虚拟内存通常比物理内存慢几个数量级。
您最好的选择是使用可以处理块的算法,或者,如果不可能,则应使用memmap
数组,这些数组至少可以允许在磁盘上就地工作,从而避免来回复制大量数据。