Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 12/07/2010, à 11:54

no_spleen

[PYTHON] forcer à vider la mémoire

Bonjour,

Je réalise des calculs scientifiques en python. J'ai une grosse fonction qui prends 2 paramètres, réalise des tas de calculs et donne 1 chiffre comme résultat. Je fais tourner cette fonction dans un algorithme spécial destiné à trouver les valeurs des paramètres qui minimisent mon résultat.

Mon problème est que les variables créées dans ma fonction ne sont pas détruite après l'appel de celle-ci, ce qui fait qu'après quelques boucles je sature ma mémoire.

Comme puis-je forcer le nettoyage des variables locales à une fonction après l'appel de celle-ci ?

Hors ligne

#2 Le 12/07/2010, à 12:01

bejazzy

Re : [PYTHON] forcer à vider la mémoire

Salut,

Ça m'arrive parfois. Pour détruire ces variables que tu n'utilises plus après calcul, tu peux faire:

del variable_1
del variable_2

etc ...

Dans le cas d'une fonction, avant de renvoyer le résultat, tu effaces ces variables (des matrices ou des vecteurs je suppose). Attention cependant à ne pas effacer des variables dont tu as encore besoin. Cette astuce m'a permis d'éviter quelques:

MemoryError

Dell Inspiron 1525 - #!CrunchBang Linux 10 Statler Xfce --- #! FR

Hors ligne

#3 Le 12/07/2010, à 13:22

no_spleen

Re : [PYTHON] forcer à vider la mémoire

J'aimerais trouver une manière de réaliser cela automatiquement, car j'ai des dizaines de fichiers de fonctions, toutes très longues.

Hors ligne

#4 Le 12/07/2010, à 14:35

bejazzy

Re : [PYTHON] forcer à vider la mémoire

Je comprends. C'est déjà une autre paire de manche !

Selon moi, Python gère la mémoire comme il l'entend. Je n'ai jamais spécifié à Python l'adresse et la place mémoire qu'allaient prendre mes différentes variables. C'est certainement faisable, mais d'une part je ne saurai comment, et d'autre part le langage permet de s'en affranchir, pourquoi ne pas en profiter ! Du coup, si tu ne sais pas où sont stockées ces variables locales déclarées dans les fonctions, tu ne pourras pas (selon moi) lui dire "efface cette partie, je n'en ai plus besoin".

Le plus simple était évidemment d'utiliser del. Mais d'après ce que tu me dis, il te faudrait changer toutes les fonctions dans tous pleins de fichiers.

La gestion de la mémoire quand tu fais du calcul scientifique n'est pas une mince affaire. Ton algorithme d'optimisation fonctionnait très bien pour des données de taille acceptable. Pour des grosses données, je ne vois pas de solution miracle:
  - passer sur une machine avec (beaucoup) plus de mémoire vive
  - revoir l'algorithme (privilégier l'écriture/lecture sur disque au stockage de toutes les données dans la mémoire vive par exemple. Ou peut-être que des variables locales aux fonctions ne sont pas nécessaires). Cette 2e solution t'oblige à modifier de toute façon des fichiers.
  - faire du calcul parallèle: calculer telle partie des données sur telle machine, une autre partie sur telle autre, faire communiquer le tout et voilou. Et là, ça nécessite encore plus de modifications.

Peut-être qu'un développeur expérimenté en Python pourra mieux t'éclairer que moi.

Remarque personnelle: je passe et repasse sur mes programmes en les modifiant pour optimiser la mémoire, le temps de calcul, améliorer la simplicité d'utilisation, ... Un programme ou un ensemble de programme sont rarement fiables, optimisés, portables, robustes, etc dès leur première implémentation. N'hésite donc pas à modifier tes programmes.


Dell Inspiron 1525 - #!CrunchBang Linux 10 Statler Xfce --- #! FR

Hors ligne

#5 Le 12/07/2010, à 14:43

HP

Re : [PYTHON] forcer à vider la mémoire

bejazzy a écrit :

Remarque personnelle: je passe et repasse sur mes programmes en les modifiant pour optimiser la mémoire, le temps de calcul, améliorer la simplicité d'utilisation, ... Un programme ou un ensemble de programme sont rarement fiables, optimisés, portables, robustes, etc dès leur première implémentation. N'hésite donc pas à modifier tes programmes.

J'approuve…

en l'occurrence, et sans voir plus de code, m'est avis qu'ici on se trouve probablement face à une grosse lacune dans le développement… après, pareil, sans plus de code et d'explications, il est difficile de situer la lacune… qui peut, par exemple, être un manque dans l'analyse.

no_spleen a écrit :

Mon problème est que les variables créées dans ma fonction ne sont pas détruite après l'appel de celle-ci, ce qui fait qu'après quelques boucles je sature ma mémoire.

Faudrait, peut-être, nous fournir un petit exemple permettant de reproduire ce phénomène et/ou de le mettre en évidence…

Dernière modification par HP (Le 12/07/2010, à 14:47)


cat /dev/urandom >/dev/null 2>&1 #github

Hors ligne

#6 Le 12/07/2010, à 21:53

tshirtman

Re : [PYTHON] forcer à vider la mémoire

J'aimerais trouver une manière de réaliser cela automatiquement, car j'ai des dizaines de fichiers de fonctions, toutes très longues.

si tu fais des fonctions plus courtes, qui retournent seulement les résultats intéressants, toutes les variables créées pendant les appels devraient disparaitre quand la fonction renvoit son résultat, un bon moyen de maitriser ta consomation est de segmenter ton code au maximum et retourner les résultats réduits plutot que des ensembles contenant l'ensemble des résultats intéressants ou non.

Aussi, la forme sous laquelle tu stoque tes résultats peut te faire économiser de la place, l'utilisation de set() plutot que de list() par exemple, te dédoublonnera tes résultats identiques s'il y en as, utiliser des générateurs quand c'est possible peut vraiment réduire ta consomation mémoire… regarde du coté des itertools pour structurer tes programmes…

Mais oui, nous donner une idée de la structure de ton programme et de tes fonctions pourrait aider…

Hors ligne

#7 Le 13/07/2010, à 08:57

no_spleen

Re : [PYTHON] forcer à vider la mémoire

Bonjour à tous,

J'ai essayé d'effacer toutes mes variables une à une en fin de chaque fonction, mais rien à faire, ma mémoire continue à baisser au cours de l'exécution.

Malheureusement, je ne suis pas autorisé à publié le code, mais je vais construire un petit exemple représentatif.

Est-ce qu'il y a moyen d'afficher toutes la variables en mémoire ? Je pourrai ainsi vérifier ce qu'il reste dans la mémoire après chaque itération.

Hors ligne

#8 Le 13/07/2010, à 09:17

no_spleen

Re : [PYTHON] forcer à vider la mémoire

J'ai trouvé la fonction dir() pour afficher les variables en mémoire, et à la fin de chaque itération toutes mes variables sont bien effacées.

Autre hypothèse. Mes fichiers de fonction utilisent tous un certain nombre de modules, souvent les mêmes (numpy,scipy,...) si j'appelle deux modules a et b, et que chacun appelle le module c, ce dernier sera-t-il chargé deux fois ?? Si oui, est-il possible d'éviter ce comportement ?

Hors ligne

#9 Le 13/07/2010, à 11:49

tshirtman

Re : [PYTHON] forcer à vider la mémoire

Non, un module n'est mis en mémoire qu'une seule fois, j'ai utilisé cette propritété pour partager des namespace (genre from config import config) et les modifier depuis deux modules différents…

à savoir: un programme peut difficilement rendre de la mémoire au systême, et python ne fait pas exception, quand tu en libère tu t'autorise à la réutiliser plus tard, elle n'est pas vraiment rendue au systême.

edit "dir" t'affiche les variables d'un namespace ou d'un objet, pas "tout".

Dernière modification par tshirtman (Le 13/07/2010, à 11:52)

Hors ligne

#10 Le 13/07/2010, à 15:40

HP

Re : [PYTHON] forcer à vider la mémoire

no_spleen a écrit :

Autre hypothèse. Mes fichiers de fonction utilisent tous un certain nombre de modules, souvent les mêmes (numpy,scipy,...) si j'appelle deux modules a et b, et que chacun appelle le module c, ce dernier sera-t-il chargé deux fois ?? Si oui, est-il possible d'éviter ce comportement ?

Importing Python Modules, on y trouve la confirmation  exacte des dires de tshirtman.


cat /dev/urandom >/dev/null 2>&1 #github

Hors ligne

#11 Le 13/07/2010, à 15:41

no_spleen

Re : [PYTHON] forcer à vider la mémoire

Comment peut-on afficher TOUT ce qui est en mémoire ?

Hors ligne

#12 Le 13/07/2010, à 19:23

Link31

Re : [PYTHON] forcer à vider la mémoire

bejazzy a écrit :

Selon moi, Python gère la mémoire comme il l'entend.

Non. Python utilise simplement un compteur de références pour ses variables. Quand une donnée n'est plus référencée, elle est automatiquement supprimée.

Seulement, il peut arriver que des dépendances circulaires apparaissent, et le système de comptage de références n'est pas toujours capable de s'en apercevoir. Dans ce cas, il peut être nécessaire de supprimer explicitement une variable, par exemple en lui assignant "None".

Python permet d'examiner la liste des objets concernés par le comptage de références :

import gc
gc.get_objects()

Mais comme la liste est généralement un peu trop longue, il est plus efficace de récupérer la liste des objets qui référencent une variable :

gc.get_referrers(une_variable)

Ou inversement, de récupérer la liste des variables que référence un objet donné :

gc.get_referents(une_instance)

http://docs.python.org/library/gc.html

Dernière modification par Link31 (Le 13/07/2010, à 19:24)

Hors ligne

#13 Le 13/07/2010, à 22:43

HP

Re : [PYTHON] forcer à vider la mémoire

Bien vu le gc de chez python !
Il est quand même, super, bien foutu ce langage… il ne cessera pas de sitôt de m'impressionner cool


cat /dev/urandom >/dev/null 2>&1 #github

Hors ligne

#14 Le 14/07/2010, à 01:32

tshirtman

Re : [PYTHON] forcer à vider la mémoire

ah oui j'avais pas pensé à en parler de lui, sans doute par ce que j'ai pas encore trop joué avec, (j'ai assez recement appris qu'on pouvait l'importer pour jouer avec), y'a surement de quoi s'amuser smile.

Hors ligne

#15 Le 14/07/2010, à 08:41

no_spleen

Re : [PYTHON] forcer à vider la mémoire

Curiosité

Si je fais à chaque itération

print sys.getsizeof(gc.get_objects())

Le nombre obtenu reste absolument constant, cela signifie que la taille des objets en mémoire reste constante non ?

Hors ligne

#16 Le 14/07/2010, à 14:57

no_spleen

Re : [PYTHON] forcer à vider la mémoire

J'ai résolu le problème de façon pragmatique en utilisant parallel python. Je lance ma fonction dans un nouveau thread que je tue une fois la réponse obtenue, libérant ainsi la mémoire.

Mais j'aimerai tout de même comprendre d'où peut venir mon problème. Je me dit que cela peut venir des librairies externes que j'utilise, par exemple la librairie getfem qui est écrtite en c++. C'est plausible ? Cela expliquerait-il que mon

gc.get_objects()

garde la même taille alors que ma mémoire diminue ?

Hors ligne