8
votes

Erreur d'allocation de mémoire Python en utilisant SubProcess.Popen

Je fais des travaux de bioinformatique. J'ai un script Python qu'à un moment donné appelle un programme pour effectuer un processus coûteux (alignement de la séquence, beaucoup de puissance et de mémoire de calcul). Je l'appelle à l'aide de subprocess.popen. Quand je l'exécute sur une témoignage, il se termine et termine bien. Cependant, lorsque je l'exécute dans le dossier complet, où il devrait le faire plusieurs fois pour différents ensembles d'entrées, il meurt. Subprocess lance:

File "..../python2.6/subprocess.py", line 1037, in _execute_child
    self.pid=os.fork()
OSError: [Errno 12] Cannot allocate memory


1 commentaires

Pouvez-vous exécuter le programme de sous-trafiscess en mode autonome, de la ligne de commande? Pouvez-vous lancer plusieurs instances les définir à l'arrière-plan (terminer la commande avec & )? Que diriez-vous de courir Time -V FOO ... Pour obtenir des statistiques sur l'utilisation des ressources informatiques du programme?


4 Réponses :


0
votes

J'exécuterais un python 64 bits sur un système d'exploitation 64 bits.

avec 32 bits, vous ne pouvez réellement obtenir que 3 Go de RAM avant que le système d'exploitation ne commence plus.

Une autre alternative peut être d'utiliser des fichiers mappés en mémoire pour ouvrir le fichier:

http://docs.python.org/library/mmap.html < / p>

EDIT: AH Vous êtes sur 64 bits .. Peut-être que la cause est que vous manquez de RAM + Swap .. La solution serait d'augmenter la quantité de swap peut-être.


3 commentaires

Je cours 64 bits aux deux extrémités. Quel est l'avantage d'utiliser un fichier mappé de mémoire vs fichiers réguliers?


Eh bien, un avantage est que vous pouvez dire au système d'exploitation d'optimiser l'accès aléatoire ou séquentiel, et vous pouvez ouvrir des fichiers plus grands que votre RAM.


L'inconvénient des fichiers mappés de mémoire est, si votre machine tombe de manière inattendue, elles sont très corruptibles.



0
votes

Cela n'a rien à voir avec Python ou le module sous-processus . SubProcess.Popen ne fait que rapporter une erreur que celle-ci reçoit du système d'exploitation. (Quel système d'exploitation utilisez-vous, à la manière?) De man 2 Fork sur Linux: xxx

appelez-vous subprocess.popen Plusieurs fois? Si oui, je pense que le mieux que vous puissiez faire est de vous assurer que l'invocation précédente de votre processus est terminée et récoltée avant l'invocation suivante.


9 commentaires

Je l'appelle plusieurs fois, mais successivement. Je jette un sous-processus.communicate () là-bas parce que je veux le stdout de chacun.


De plus, si cela manque de mémoire, pourquoi ne peut-il utiliser Linux d'utiliser un swapsile (la machine est une ressource partagée et a 64 g de RAM, donc je pense qu'il n'a pas d'espace d'échange défini)?


@jmerkin, utilisez swapon -s Pour savoir si un swap est configuré, utilisez gratuit pour indiquer à quel point la mémoire physique et l'espace d'échange sont libres que vous avez. Si vous n'avez pas d'échange, la configuration de Swap est une solution pour augmenter la mémoire virtuelle disponible. De plus, je vous recommande de répondre à la question de @konstantin Tenzin. Utilisez-vous réellement le résultat de la sous-processus (stdout / stardr)? Si oui, le résultat est-il grand? Si oui, que faites-vous pour vous assurer que votre processus Python ne consomme pas la mémoire disponible?


Oui, échanger et mémoire est abondant. J'utilise le résultat de stdout et il sera au plus quelques mégaoctets. De toute façon, je le veux écrit dans un fichier. J'ai essayé d'utiliser stdout = sous-processus.pipe ainsi que 'Subprocess.Popen (' Foo> Bar ', Shell = TRUE, STDRERR = SUBPROCESS.PIPE) Pour l'écrire au fichier. les deux ont donné l'erreur.


@jmerkin, l'argument stdout peut prendre un "objet de fichier", par ex. subprocess.popen ("foo", stdout = ouvert ("bar", "w")) . ulimit -a signalez-vous quelque chose de surprenant?


ça va me sauver quelques lignes de code, merci. Non, Ulimit -a a l'air plutôt ok et les valeurs correspondent à celles de la ressource.rlimit dites-moi, alors Python ne pense pas quelque chose de différent de la machine.


Votre processus Python est-il très grand en mémoire? Vous avez une manière d'une manière ou d'une autre que vous avez convaincu le noyau que cela ne puisse pas forger votre processus de python. Peut-être que votre processus Python est grand (comme dans, a de nombreuses entrées de table de page). Peut-être que vous frappez un autre type de limite de ressources. S'il s'agit d'un problème de gros processus de python, alors lorsque subprocess.popen ("FOO") échoue, fondamentalement, tous les autres sous-processus.popen Les appels doivent également échouer. Essayez-le: Essayez: ... Sauf OsError: Subprocess.Popen ("LS") (doit échouer avec la même erreur), et en outre, si vous appelez FOO d'une coquille, cela devrait fonctionner.


@rlibby c'est assez gros. J'ai confiné le sous-processus d'utiliser moins de RAM en l'alimentant un paramètre. Je suis intéressé par la limite, si quelqu'un a une idée. Je ne vois pas pourquoi cela ne devrait pas commencer à utiliser un échange avant de mourir.


@jmerkin, je parierai que le problème est la taille de votre processus de python. Essayez un schéma qui utilise clone / EXEC au lieu de Fourche / exec . Python's OS.SPOWN Empireusement de la famille semble pour faire ça. (Vérifiez-vous avec strace -f .) Malheureusement, cela signifiera un peu plus de comptabilité de processus à votre fin.



0
votes

Utilisez-vous sous-traduces.pipe? J'ai eu des problèmes et j'ai lu des problèmes quand il a été utilisé. Les fichiers temporaires ont généralement résolu le problème.


1 commentaires

J'ai essayé les deux sens. J'ai essayé directement d'écrire dans un fichier ainsi que sous-processus.pipe: A = sous-processus.popen ('foo> bar', shell = true, stardr = subchrocessité.pipe); A.WAIT ()) A = Subprocess.Popen (FOO, STDOUT = SUBPROCESS.PIPE, STDERR = SUBPROC ESS.PIPIPE) F_OUT.WRITE (A. 0] [0]) et cela m'a également donné cette erreur. Stderr est assez négligeable, quelques lignes au plus à cause des progrès du programme, il ne devrait donc pas être grand chose.



13
votes

Je me sens vraiment désolé pour l'op. 6 ans plus tard et personne n'a indiqué qu'il s'agissait d'un problème très courant dans UNIX et n'a rien à voir avec python ou bioinformatique. Un appel à Os.fork () double temporairement la mémoire du processus parent (la mémoire du processus parent doit être disponible pour le processus d'enfant), avant de tout jeter pour faire un EXED (). Bien que cette mémoire ne soit pas toujours copiée, le système doit avoir suffisamment de mémoire pour pouvoir être copié. Ainsi, si votre processus parent utilise plus de la moitié de la mémoire du système et que vous subventionnez même "WC -L -L ", vous allez courir dans une erreur de mémoire.

La solution consiste à utiliser POSIX_SPOWN, ou à créer toutes vos sous-processus au début du script, tandis que la consommation de mémoire est faible, puis utilisez-les plus tard après que le processus parent ait fait une chose intensive de mémoire.

Une recherche Google à l'aide des travaux-clés "Os.fork" et "Memory" affichera plusieurs poteaux de dépassement de pile sur la rubrique qui peut expliquer davantage ce qui se passe :)


0 commentaires