Jupyter Lab gèle l'ordinateur en cas de manque de RAM - comment l'empêcher?

12

J'ai récemment commencé à utiliser Jupyter Lab et mon problème est que je travaille avec des ensembles de données assez volumineux (généralement l'ensemble de données lui-même représente environ 1/4 de la RAM de mon ordinateur). Après quelques transformations, enregistrées en tant que nouveaux objets Python, j'ai tendance à manquer de mémoire. Le problème est que lorsque j'approche de la limite de RAM disponible et que j'effectue une opération qui nécessite un autre espace RAM, mon ordinateur se bloque et la seule façon de le réparer est de le redémarrer. S'agit-il d'un comportement par défaut dans Jupyter Lab / Notebook ou s'agit-il de paramètres que je devrais définir? Normalement, je m'attendrais à ce que le programme tombe en panne (comme dans RStudio par exemple), pas tout l'ordinateur

jakes
la source
J'ai eu le même problème avant, c'est vraiment méchant. J'ai jeté un coup d'œil aux problèmes de jupyter et je n'ai rien trouvé. Cela se produit-il également si vous exécutez via la console IPython (pas en python ordinaire)?
Bzazz
Quel package / module avez-vous utilisé? De quel OS s'agit-il? Avez-vous échangé? Quelle version de Jupyter Lab? Si c'était Linux quelle était la version du noyau?
Nizam Mohamed
Il s'agit principalement de Pandas, mais je ne pense pas que ce soit lié au package. Le système d'exploitation est Ubuntu 16.04.6 LTS et la version du noyau est 4.15.0-65-générique. La version de Jupyter Lab est 1.0.2. J'ai un SWAP réglé sur 12 Go (attribué à 2 fichiers), ce qui correspond à 1,5 de ma RAM.
jakes

Réponses:

5

La solution la plus robuste à ce problème serait d'utiliser des conteneurs Docker. Vous pouvez spécifier la quantité de mémoire à allouer à Jupyter, et si le conteneur manque de mémoire, ce n'est tout simplement pas un gros problème (n'oubliez pas de sauvegarder fréquemment, mais cela va sans dire).

Ce blog vous y mènera la plupart du temps. Il existe également des instructions décentes pour configurer Jupyter Lab à partir d'une des images Jupyter disponibles gratuitement et officiellement maintenues ici:

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

puis vous pouvez modifier la docker runcommande comme décrit dans le tutoriel comme (par exemple pour 3 Go):

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

Pour obtenir la syntaxe des options de mémoire du docker, consultez cette question:

À quelle unité le docker exécute-t-il l'option "--memory"?

kd88
la source
4

Si vous utilisez Ubuntu, consultez les tueurs OOM, vous pouvez obtenir des informations ici

Vous pouvez utiliser earlyoom . Il peut être configuré comme vous le souhaitez, par exemple earlyoom -s 90 -m 15, démarrera le earlyoomet lorsque la taille du swap est inférieure à% 90 et la mémoire est inférieure à% 15, il tuera le processus qui provoque OOM et empêchera le système entier de geler. Vous pouvez également configurer la priorité des processus.

emremrah
la source
2

Je travaille également avec des ensembles de données très volumineux (3 Go) sur Jupyter Lab et j'ai rencontré le même problème sur Labs. Il n'est pas clair si vous devez conserver l'accès aux données prétraitées, sinon, j'ai commencé à utiliser delde grandes variables de trame de données inutilisées si je n'en ai pas besoin. delsupprime les variables de votre mémoire. Edit **: il existe plusieurs possibilités pour le problème que je rencontre. Je rencontre cela plus souvent lorsque j'utilise une instance jupyter distante, et dans spyder également lorsque je réalise de grandes transformations.

par exemple

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

Jakes, vous pouvez également trouver ce fil sur les workflows de données volumineux utile. J'ai cherché dans Dask pour aider au stockage de la mémoire.

J'ai remarqué dans spyder et jupyter que le blocage se produit généralement lorsque vous travaillez dans une autre console pendant qu'une grande console de mémoire fonctionne. Quant à savoir pourquoi il se fige juste au lieu de s'écraser, je pense que cela a quelque chose à voir avec le noyau. Il y a quelques problèmes de mémoire ouverts dans le github IPython - # 10082 et # 10117 semblent les plus pertinents. Un utilisateur ici suggère de désactiver la complétion des onglets dans jediou de mettre à jour le jedi.

En 10117, ils proposent de vérifier la sortie de get_ipython().history_manager.db_log_output. J'ai les mêmes problèmes et mon réglage est correct, mais cela vaut la peine d'être vérifié

Elizabeth
la source
1

Vous pouvez également utiliser des blocs-notes dans le cloud, comme Google Colab ici . Ils ont fourni la facilité pour les RAM recommandées et la prise en charge du bloc-notes Jupyter est par défaut.

Jishan Shaikh
la source
0

Je pense que vous devriez utiliser des morceaux. Comme ça:

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)

Pour plus d'informations, consultez-le: https://towardsdatascience.com/why-and-how-to-use-pandas-with-large-data-9594dda2ea4c

Je suggère de ne pas ajouter à nouveau une liste (probablement la RAM va surcharger à nouveau). Vous devriez terminer votre travail dans cette boucle.

Berkay
la source
Je pense que le problème ici n'est pas de savoir comment ne pas manquer de mémoire, mais comment éviter que l'ordinateur ne plante et ne nécessite un redémarrage. Python devrait planter ou lancer une erreur de mémoire, mais ne pas tout gâcher.
Bzazz
0

Je vais résumer les réponses à la question suivante . Vous pouvez limiter l'utilisation de la mémoire de votre programme. Dans la suite, ce sera la fonction ram_intense_foo(). Avant d'appeler, vous devez appeler la fonctionlimit_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
la source
-4

Il n'y a aucune raison d'afficher la sortie entière d'une grande trame de données. L'affichage ou la manipulation de grandes trames de données utilisera inutilement de grandes quantités de ressources informatiques.

Tout ce que vous faites peut se faire en miniature. Il est beaucoup plus facile de travailler sur le codage et la manipulation de données lorsque la trame de données est petite. La meilleure façon de travailler avec des données volumineuses est de créer une nouvelle trame de données qui ne prend qu'une petite partie ou un petit échantillon de la grande trame de données. Ensuite, vous pouvez explorer les données et effectuer votre codage sur la plus petite trame de données. Une fois que vous avez exploré les données et que votre code fonctionne, utilisez simplement ce code sur le bloc de données plus grand.

La manière la plus simple consiste simplement à prendre le premier n, nombre des premières lignes de la trame de données à l'aide de la fonction head (). La fonction head n'imprime que n, nombre de lignes. Vous pouvez créer une mini trame de données en utilisant la fonction head sur la grande trame de données. Ci-dessous, j'ai choisi de sélectionner les 50 premières lignes et de transmettre leur valeur au small_df. Cela suppose que le BigData est un fichier de données provenant d'une bibliothèque que vous avez ouverte pour ce projet.

library(namedPackage) 

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

Cela fonctionnera la plupart du temps, mais parfois la trame Big Data est fournie avec des variables pré-triées ou avec des variables déjà groupées. Si les mégadonnées sont comme ceci, vous devrez alors prélever un échantillon aléatoire des lignes des mégadonnées. Utilisez ensuite le code qui suit:

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
la source