Jupyter Lab congela la computadora cuando no tiene RAM: ¿cómo prevenirla?

12

Recientemente comencé a usar Jupyter Lab y mi problema es que trabajo con conjuntos de datos bastante grandes (generalmente el conjunto de datos en sí es aproximadamente 1/4 de la RAM de mi computadora). Después de algunas transformaciones, guardadas como nuevos objetos de Python, tiendo a quedarme sin memoria. El problema es que cuando me acerco al límite de RAM disponible y realizo cualquier operación que necesite otro espacio de RAM, mi computadora se congela y la única forma de solucionarlo es reiniciarlo. ¿Es este un comportamiento predeterminado en Jupyter Lab / Notebook o hay algunas configuraciones que debo establecer? Normalmente, esperaría que el programa se bloquee (como en RStudio, por ejemplo), no toda la computadora

jakes
fuente
Tuve el mismo problema antes, es realmente desagradable. Eché un vistazo rápido a los problemas de jupyter y no encontré nada. ¿Ocurre también si se ejecuta a través de la consola IPython (no Python simple)?
Bzazz
¿Qué paquete / módulo usaste? ¿Qué sistema operativo es? ¿Tuviste un intercambio? ¿Qué versión de Jupyter Lab? Si fue Linux, ¿cuál es la versión del kernel?
Nizam Mohamed el
Es principalmente Pandas, pero no creo que esté relacionado con el paquete. El sistema operativo es Ubuntu 16.04.6 LTS y la versión del kernel es 4.15.0-65-generic. La versión de Jupyter Lab es 1.0.2. Tengo un SWAP configurado en 12 GB (asignado a 2 archivos) que es 1.5 de mi RAM.
jakes

Respuestas:

5

Absolutamente la solución más sólida para este problema sería usar contenedores Docker. Puede especificar cuánta memoria asignar a Jupyter, y si el contenedor se queda sin memoria, simplemente no es gran cosa (solo recuerde guardar con frecuencia, pero eso es evidente).

Este blog te llevará la mayor parte del camino. También hay algunas instrucciones decentes que configuran Jupyter Lab a partir de una de las imágenes de Jupyter disponibles gratuitamente y mantenidas oficialmente aquí:

https://medium.com/fundbox-engineering/overview-d3759e83969c

y luego puede modificar el docker runcomando como se describe en el tutorial como (por ejemplo, para 3GB):

docker run --memory 3g <other docker run args from tutorial here>

Para ver la sintaxis de las opciones de memoria de la ventana acoplable, consulte esta pregunta:

¿Qué unidad espera la opción "--memory" de la ventana acoplable?

kd88
fuente
4

Si está utilizando Ubuntu, consulte los asesinos de OOM, puede obtener información desde aquí

Puedes usar temprano . Se puede configurar como lo desee, por ejemplo earlyoom -s 90 -m 15, iniciará earlyoomy cuando el tamaño de intercambio sea inferior a% 90 y la memoria sea inferior a% 15, matará el proceso que causa OOM y evitará que todo el sistema se congele. También puede configurar la prioridad de los procesos.

emremrah
fuente
2

También trabajo con conjuntos de datos muy grandes (3GB) en Jupyter Lab y he estado experimentando el mismo problema en Labs. No está claro si necesita mantener el acceso a los datos delpretransformados ; si no, he comenzado a usar variables de trama de datos grandes no utilizadas si no las necesito. delelimina variables de tu memoria. Editar **: hay múltiples posibilidades para el problema que estoy encontrando. Encuentro esto más a menudo cuando uso una instancia remota de jupyter, y también en Spyder cuando realizo grandes transformaciones.

p.ej

df = pd.read('some_giant_dataframe') # or whatever your import is
new_df = my_transform(df)
del df # if unneeded.

Jakes también puede encontrar útil este hilo en flujos de trabajo de datos grandes . He estado buscando en Dask para ayudar con el almacenamiento de memoria.

He notado en Spyder y Jupyter que el congelamiento generalmente ocurre cuando se trabaja en otra consola mientras se ejecuta una consola de memoria grande. En cuanto a por qué simplemente se congela en lugar de estrellarse, creo que esto tiene algo que ver con el núcleo. Hay un par de problemas de memoria abiertos en el github de IPython : # 10082 y # 10117 parecen más relevantes. Un usuario aquí sugiere deshabilitar la finalización de la pestaña jedio actualizar jedi.

En 10117 proponen comprobar la salida de get_ipython().history_manager.db_log_output. Tengo los mismos problemas y mi configuración es correcta, pero vale la pena verificar

Elizabeth
fuente
1

También puede usar portátiles en la nube, como Google Colab aquí . Han proporcionado la facilidad para RAM recomendadas y el soporte para el portátil Jupyter es por defecto.

Jishan Shaikh
fuente
0

Creo que deberías usar trozos. Como eso:

df_chunk = pd.read_csv(r'../input/data.csv', chunksize=1000000)
chunk_list = []  # append each chunk df here 

# Each chunk is in df format
for chunk in df_chunk:  
    # perform data filtering 
    chunk_filter = chunk_preprocessing(chunk)

    # Once the data filtering is done, append the chunk to list
    chunk_list.append(chunk_filter)

# concat the list into dataframe 
df_concat = pd.concat(chunk_list)

Para obtener más información, échale un vistazo: https://towardsdatascience.com/why-and-how-to-use-pandas-with-large-data-9594dda2ea4c

Sugiero que no agregue una lista nuevamente (probablemente la RAM se sobrecargará nuevamente). Deberías terminar tu trabajo en ese ciclo for.

Berkay
fuente
Creo que el problema aquí no es cómo no quedarse sin memoria, sino cómo evitar que la computadora se bloquee y necesite reiniciarse. Python debería bloquearse o lanzar un error de memoria, pero no estropear todo.
Bzazz
0

Voy a resumir las respuestas de la siguiente pregunta . Puede limitar el uso de memoria de su programa. A continuación, esta será la función ram_intense_foo(). Antes de llamar, debe llamar a la funciónlimit_memory(10)

import resource
import platform
import sys
import numpy as np 

def memory_limit(percent_of_free):
    soft, hard = resource.getrlimit(resource.RLIMIT_AS)
    resource.setrlimit(resource.RLIMIT_AS, (get_memory() * 1024 * percent_of_free / 100, hard))

def get_memory():
    with open('/proc/meminfo', 'r') as mem:
        free_memory = 0
        for i in mem:
            sline = i.split()
            if str(sline[0]) == 'MemAvailable:':
                free_memory = int(sline[1])
                break
    return free_memory

def ram_intense_foo(a,b):
    A = np.random.rand(a,b)
    return A.T@A

if __name__ == '__main__':
    memory_limit(95)
    try:
        temp = ram_intense_foo(4000,10000)
        print(temp.shape)
    except MemoryError:
        sys.stderr.write('\n\nERROR: Memory Exception\n')
        sys.exit(1)
v.tralala
fuente
-4

No hay ninguna razón para ver la salida completa de un gran marco de datos. Ver o manipular grandes marcos de datos utilizará innecesariamente grandes cantidades de los recursos de su computadora.

Lo que sea que esté haciendo se puede hacer en miniatura. Es mucho más fácil trabajar en la codificación y manipulación de datos cuando el marco de datos es pequeño. La mejor manera de trabajar con big data es crear un nuevo marco de datos que tome solo una pequeña porción o una pequeña muestra del gran marco de datos. Luego puede explorar los datos y codificar en el marco de datos más pequeño. Una vez que haya explorado los datos y haga funcionar su código, simplemente use ese código en el marco de datos más grande.

La forma más fácil es simplemente tomar el primer n, número de las primeras filas del marco de datos utilizando la función head (). La función head solo imprime n, número de filas. Puede crear un mini marco de datos utilizando la función de cabeza en el marco de datos grande. A continuación, elegí seleccionar las primeras 50 filas y pasar su valor a small_df. Esto supone que BigData es un archivo de datos que proviene de una biblioteca que abrió para este proyecto.

library(namedPackage) 

df <- data.frame(BigData)                #  Assign big data to df
small_df <- head(df, 50)         #  Assign the first 50 rows to small_df

Esto funcionará la mayor parte del tiempo, pero a veces el marco de datos grandes viene con variables preseleccionadas o con variables ya agrupadas. Si los datos grandes son así, necesitaría tomar una muestra aleatoria de las filas de los datos grandes. Luego use el código que sigue:

df <- data.frame(BigData)

set.seed(1016)                                          # set your own seed

df_small <- df[sample(nrow(df),replace=F,size=.03*nrow(df)),]     # samples 3% rows
df_small                                                         # much smaller df
gris
fuente