No se puede asignar una matriz con forma y tipo de datos

Resuelto Martin Brisiak asked hace 5 años • 8 respuestas

Tengo un problema al asignar matrices enormes en numpy en Ubuntu 18, mientras que no tengo el mismo problema en MacOS.

Estoy intentando asignar memoria para una matriz numerosa con forma (156816, 36, 53806) con

np.zeros((156816, 36, 53806), dtype='uint8')

y mientras recibo un error en el sistema operativo 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

No 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)

Leí en alguna parte que np.zerosen realidad no debería asignarse 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.0

PD: también falló en Google Colab

Martin Brisiak avatar Aug 15 '19 16:08 Martin Brisiak
Aceptado

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 sobrecompromiso. Se rechazan los compromisos excesivos obvios del espacio de direcciones. Utilizado para un sistema típico. Garantiza que una asignación grave falle y al mismo tiempo permite un compromiso excesivo para reducir el uso de swap. 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 se analiza 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
0

En este caso, estás asignando

>>> 156816 * 36 * 53806 / 1024.0**3
282.8939827680588

~ 282 GB y el kernel dice: bueno, obviamente no hay manera de que pueda asignar tantas páginas físicas a esto, y rechaza la asignación.

Si (como root) ejecutas:

$ echo 1 > /proc/sys/vm/overcommit_memory

Esto habilitará el modo "siempre sobrecompromiso" y descubrirá que, de hecho, el sistema le permitirá realizar la asignación sin importar cuán grande sea (al menos dentro del direccionamiento de memoria de 64 bits).

Lo probé yo mismo en una máquina con 32 GB de RAM. Con el modo de sobrecompromiso 0también obtuve un MemoryError, pero después de cambiarlo nuevamente 1funciona:

>>> import numpy as np
>>> a = np.zeros((156816, 36, 53806), dtype='uint8')
>>> a.nbytes
303755101056

Luego 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 puedes usar esto, con cuidado, para arreglos dispersos.

Iguananaut avatar Aug 15 '2019 14:08 Iguananaut

Tuve el 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 para mí también era un problema de compromiso excesivo de memoria.

ventana 8

  1. En el teclado Presione la tecla Windows + X y luego haga clic en Sistema en el menú emergente
  2. Toque o haga clic en Configuración avanzada del sistema. Es posible que se le solicite una contraseña de administrador o que confirme su elección.
  3. En la pestaña Avanzado, en Rendimiento, toque o haga clic en Configuración.
  4. Toque o haga clic en la pestaña Avanzado y luego, en Memoria virtual, toque o haga clic en Cambiar
  5. Desactive la casilla de verificación Administrar automáticamente el tamaño del archivo de paginación para todas las unidades.
  6. En Unidad [Etiqueta de volumen], toque o haga clic en la unidad que contiene el archivo de paginación que desea cambiar.
  7. Toque o haga clic en Tamaño personalizado, ingrese un nuevo tamaño en megabytes en el cuadro Tamaño inicial (MB) o Tamaño máximo (MB), toque o haga clic en Establecer y luego toque o haga clic en Aceptar.
  8. Reinicie su sistema

ventanas 10

  1. Presione la tecla de Windows
  2. Tipo Propiedades del sistema Avanzado
  3. Haga clic en Ejecutar como administrador
  4. En Rendimiento, haga clic en Configuración
  5. Seleccione la pestaña Avanzado
  6. Seleccione Cambiar...
  7. Desmarque Administrar automáticamente el tamaño del archivo de paginación para todas las unidades
  8. Luego seleccione Tamaño personalizado y complete el tamaño apropiado
  9. Presione Establecer, luego presione Aceptar y luego salga del cuadro de diálogo Memoria virtual, Opciones de rendimiento y Propiedades del sistema.
  10. Reinicie su sistema

Nota: No tenía suficiente memoria en mi sistema para los ~282 GB de este ejemplo, pero en mi caso particular funcionó.

EDITAR

Desde 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 tienes 4 GB (1 GB = 1024 MB x 4 = 4096 MB) de memoria. El tamaño inicial sería 1,5 x 4.096 = 6.144 MB y el tamaño máximo sería 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 ni 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 paginación más grande agregará trabajo adicional a su disco duro, lo que hará que todo lo demás funcione más lento. El tamaño del archivo de página sólo debe aumentarse cuando se produzcan errores de falta de memoria y sólo como solución temporal. Una mejor solución es agregar más memoria a la computadora.

recurseuntilfor avatar Nov 04 '2019 03:11 recurseuntilfor

También encontré este problema en Windows. 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 gestionar un máximo de 4 GB de RAM (2^32). Por lo que si tienes más de 4 GB de RAM, una versión de 32 bits no podrá aprovecharla.

Con una versión de Python de 64 bits (la que está etiquetada como x86-64 en la página de descarga), el problema desaparece.

Puedes comprobar qué versión tienes 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 64 bit (AMD64)] significa "Python de 64 bits".

Fuentes:

  • Quora: error de memoria generado por una gran matriz numerosa

  • Stackoverflow: versión de Python de 32 o 64 bits

kotchwane avatar Nov 29 '2019 08:11 kotchwane

En mi caso, agregar un atributo dtype cambió el tipo d de la matriz a un tipo más pequeño (de float64 a uint8), disminuyendo el tamaño de la matriz lo suficiente como para no generar MemoryError en Windows (64 bits).

de

mask = np.zeros(edges.shape)

a

mask = np.zeros(edges.shape,dtype='uint8')
Pragya Agrawal avatar Jan 21 '2020 08:01 Pragya Agrawal