为什么在8GB内存macOS计算机上可以使用352GB NumPy ndarray?

Bla*_*ang 24 python memory macos numpy

import numpy as np

array = np.zeros((210000, 210000)) # default numpy.float64
array.nbytes
Run Code Online (Sandbox Code Playgroud)

当我在带有macOS的8GB内存MacBook上运行上述代码时,不会发生错误.但是在配备Windows 10的16GB内存PC或12GB内存Ubuntu笔记本电脑上运行相同的代码,甚至在128GB内存的Linux超级计算机上运行相同的代码,Python解释器将引发MemoryError.所有测试环境都安装了64位Python 3.6或3.7.

use*_*561 23

@Martijn Pieters的回答是正确的,但并不完全正确:这与内存压缩无关,而是与虚拟内存有关.

例如,尝试在您的计算机上运行以下代码:

arrays = [np.zeros((21000, 21000)) for _ in range(0, 10000)]
Run Code Online (Sandbox Code Playgroud)

这段代码分配32TiB的内存,但你不会得到错误(至少我没有,在Linux上).如果我检查htop,我会看到以下内容:

  PID USER      PRI  NI  VIRT   RES   SHR S CPU% MEM%   TIME+  Command
31362 user       20   0 32.1T 69216 12712 S  0.0  0.4  0:00.22 python
Run Code Online (Sandbox Code Playgroud)

这是因为操作系统完全愿意过度使用虚拟内存.在需要之前,它实际上不会将页面分配给物理内存.它的工作方式是:

  • calloc 要求操作系统使用一些内存
  • 操作系统查看进程的页表,并找到它愿意分配的一块内存.这是快速操作,OS只是将内存地址范围存储在内部数据结构中.
  • 程序写入其中一个地址.
  • 操作系统收到页面错误,此时它会查看并实际将页面分配给物理内存.页面大小通常为几KiB.
  • 操作系统将控制权传递给程序,程序继续进行而不会注意到中断.

我不知道为什么创建一个巨大的阵列在Linux或Windows上不起作用,但是我希望它与平台的libc 0x3BAFFFFFF实现有更多的关系,并且比操作系统强加的限制.

为了好玩,试试跑步echo 1 | sudo tee /proc/sys/vm/overcommit_memory.即使在使用交换压缩的MacOs或Linux上,您肯定会出现内存不足错误.是的,某些操作系统可以压缩RAM,但是它们无法将其压缩到不会耗尽内存的水平.