¿Por qué se puede usar un ndarray NumPy de 352 GB en una computadora macOS con memoria de 8 GB?

import numpy as np array = np.zeros((210000, 210000)) # default numpy.float64 array.nbytes 

Cuando ejecuto el código anterior en mi MacBook de memoria de 8GB con macOS, no se produce ningún error. Pero ejecutando el mismo código en una PC de memoria de 16GB con Windows 10 o una computadora portátil Ubuntu de 12GB de memoria, o incluso en una supercomputadora Linux de 128GB de memoria, el intérprete de Python generará un error de memoria. Todos los entornos de prueba tienen Python 3.6 o 3.7 de 64 bits instalado.

La respuesta de @Martijn Pieters está en el camino correcto, pero no del todo correcto: esto no tiene nada que ver con la compresión de la memoria, sino que tiene que ver con la memoria virtual .

Por ejemplo, intente ejecutar el siguiente código en su máquina:

 arrays = [np.zeros((21000, 21000)) for _ in range(0, 10000)] 

Este código asigna 32 TB de memoria, pero no obtendrá un error (al menos no lo hice, en Linux). Si reviso htop, veo lo siguiente:

  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 

Esto porque el sistema operativo está perfectamente dispuesto a cometer en exceso en la memoria virtual . En realidad, no asignará páginas a la memoria física hasta que sea necesario. La forma en que funciona es:

  • calloc le pide al sistema operativo algo de memoria para usar
  • el sistema operativo busca en las tablas de páginas del proceso y encuentra un trozo de memoria que está dispuesto a asignar. Esta es una operación rápida, el sistema operativo solo almacena el rango de direcciones de memoria en una estructura de datos interna.
  • El progtwig escribe a una de las direcciones.
  • el sistema operativo recibe un error de página , en cuyo punto se ve y en realidad asigna la página a la memoria física. Una página suele ser de unos pocos KiB de tamaño .
  • el sistema operativo pasa el control de nuevo al progtwig, que continúa sin darse cuenta de la interrupción.

La creación de una gran matriz única no funciona en Linux porque, de forma predeterminada, se aplica un “algoritmo heurístico para determinar si hay suficiente memoria disponible”. (¡ Gracias a @Martijn Pieters! ) Algunos experimentos en mi sistema muestran que para mí, el kernel no está dispuesto a proporcionar más de 0x3BAFFFFFF bytes. Sin embargo, si ejecuto echo 1 | sudo tee /proc/sys/vm/overcommit_memory echo 1 | sudo tee /proc/sys/vm/overcommit_memory , y luego vuelva a intentar el progtwig en el OP, funciona bien.

Para divertirse, intente ejecutar arrays = [np.ones((21000, 21000)) for _ in range(0, 10000)] . Definitivamente obtendrá un error de falta de memoria, incluso en MacOs o Linux con compresión de intercambio. Sí, ciertos sistemas operativos pueden comprimir la RAM, pero no pueden comprimirla al nivel que no se quedaría sin memoria.