Me enfrento a un problema con la asignación de matrices enormes en numpy en Ubuntu 18 sin enfrentar el mismo problema en MacOS.
Estoy tratando de asignar memoria para una matriz numpy con forma (156816, 36, 53806) con
np.zeros((156816, 36, 53806), dtype='uint8')y mientras recibo un error en Ubuntu OS
>>> 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 uint8No lo obtengo en 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) He leído en alguna parte que np.zeros no debería asignar realmente toda la memoria necesaria para la matriz, sino solo para los elementos distintos de cero. Aunque la máquina Ubuntu tiene 64 gb de memoria, mientras que mi MacBook Pro solo tiene 16 gb.
versiones:
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.0PD: también falló en Google Colab
Es probable que esto se deba al modo de manejo de compromiso excesivo de su sistema.
En el modo predeterminado, 0 ,
Manejo heurístico de compromisos excesivos. Se rechazan los compromisos excesivos obvios del espacio de direcciones. Se utiliza para un sistema típico. Garantiza que falla una asignación seriamente salvaje al tiempo que permite un compromiso excesivo para reducir el uso de intercambio. La raíz puede asignar un poco más de memoria en este modo. Este es el valor predeterminado.
La heurística exacta utilizada no se explica bien aquí, pero esto se discute más en Linux sobre la heurística de confirmación y en esta página .
Puede verificar su modo de sobrecompromiso actual ejecutando
$ cat /proc/sys/vm/overcommit_memory 0En este caso, estás asignando
>>> 156816 * 36 * 53806 / 1024.0**3 282.8939827680588~282 GB y el kernel dice que obviamente no hay forma de que pueda asignar tantas páginas físicas a esto, y rechaza la asignación.
Si (como root) ejecuta:
$ echo 1 > /proc/sys/vm/overcommit_memoryEsto habilitará el modo "siempre sobreasignado", y encontrará que, de hecho, el sistema le permitirá realizar la asignación sin importar cuán grande sea (al menos dentro de un direccionamiento de memoria de 64 bits).
Probé esto yo mismo en una máquina con 32 GB de RAM. Con el modo de compromiso excesivo 0 también obtuve un MemoryError , pero después de volver a cambiarlo a 1 funciona:
>>> import numpy as np >>> a = np.zeros((156816, 36, 53806), dtype='uint8') >>> a.nbytes 303755101056Luego puede continuar y escribir en cualquier ubicación dentro de la matriz, y el sistema solo asignará páginas físicas cuando escriba explícitamente en esa página. Entonces puede usar esto, con cuidado, para arreglos dispersos.
Tuve este mismo problema en Windows y encontré esta solución. Entonces, si alguien se encuentra con este problema en Windows, la solución para mí fue aumentar el tamaño del archivo de paginación , ya que también era un problema de sobreasignación de memoria para mí.
ventanas 8
ventanas 10
Nota: No tenía suficiente memoria en mi sistema para los ~282 GB de este ejemplo, pero en mi caso particular funcionó.
EDITAR
A partir de aquí las recomendaciones sugeridas para el tamaño del archivo de página:
Existe una fórmula para calcular el tamaño correcto del archivo de paginación. El tamaño inicial es uno y medio (1,5) x la cantidad de memoria total del sistema. El tamaño máximo es tres (3) x el tamaño inicial. Entonces, digamos que tiene 4 GB (1 GB = 1024 MB x 4 = 4096 MB) de memoria. El tamaño inicial sería de 1,5 x 4.096 = 6.144 MB y el tamaño máximo sería de 3 x 6.144 = 18.432 MB.
Algunas cosas a tener en cuenta desde aquí :
Sin embargo, esto no tiene en cuenta otros factores importantes y configuraciones del sistema que pueden ser exclusivos de su computadora. Nuevamente, deje que Windows elija qué usar en lugar de confiar en alguna fórmula arbitraria que funcionó en una computadora diferente.
También:
Aumentar el tamaño del archivo de página puede ayudar a prevenir inestabilidades y fallas en Windows. Sin embargo, los tiempos de lectura/escritura de un disco duro son mucho más lentos de lo que serían si los datos estuvieran en la memoria de su computadora. Tener un archivo de página más grande agregará trabajo adicional para su disco duro, lo que hará que todo lo demás funcione más lentamente. El tamaño del archivo de página solo debe aumentarse cuando se encuentran errores de falta de memoria, y solo como una solución temporal. Una mejor solución es agregar más memoria a la computadora.
Me encontré con este problema en Windows también. La solución para mí fue cambiar de una versión de Python de 32 bits a una de 64 bits . De hecho, un software de 32 bits, como una CPU de 32 bits, puede ocupar un máximo de 4 GB de RAM (2^32). Entonces, si tiene más de 4 GB de RAM, una versión de 32 bits no puede aprovecharla.
Con una versión de Python de 64 bits (la etiquetada como x86-64 en la página de descarga), el problema desaparece.
Puede verificar qué versión tiene ingresando al intérprete. Yo, con una versión de 64 bits, ahora tengo: Python 3.7.5rc1 (tags/v3.7.5rc1:4082f600a5, Oct 1 2019, 20:28:14) [MSC v.1916 64 bit (AMD64)] , donde [ MSC v.1916 de 64 bits (AMD64)] significa "Python de 64 bits".
Fuentes: