J'ai vu quelques articles sur l'utilisation de la mémoire en utilisant Python Module multiprocessing. Cependant, les questions ne semblent pas répondre au problème que j'ai ici. Je publie mon analyse avec l'espoir que quelqu'un peut m'aider.
J'utilise le multitraitement pour effectuer des tâches en parallèle et j'ai remarqué que la consommation de mémoire par les processus de travail augmente indéfiniment. J'ai un petit exemple autonome qui devrait reproduire ce que je remarque.
import multiprocessing as mp
import time
def calculate(num):
l = [num*num for num in range(num)]
s = sum(l)
del l # delete lists as an option
return s
if __== "__main__":
pool = mp.Pool(processes=2)
time.sleep(5)
print "launching calculation"
num_tasks = 1000
tasks = [pool.apply_async(calculate,(i,)) for i in range(num_tasks)]
for f in tasks:
print f.get(5)
print "calculation finished"
time.sleep(10)
print "closing pool"
pool.close()
print "closed pool"
print "joining pool"
pool.join()
print "joined pool"
time.sleep(5)
J'utilise Windows et j'utilise le gestionnaire de tâches pour surveiller l'utilisation de la mémoire. J'exécute Python 2.7.6.
J'ai résumé la consommation de mémoire par les 2 processus de travail ci-dessous.
+---------------+----------------------+----------------------+
| num_tasks | memory with del | memory without del |
| | proc_1 | proc_2 | proc_1 | proc_2 |
+---------------+----------------------+----------------------+
| 1000 | 4884 | 4694 | 4892 | 4952 |
| 5000 | 5588 | 5596 | 6140 | 6268 |
| 10000 | 6528 | 6580 | 6640 | 6644 |
+---------------+----------------------+----------------------+
Dans le tableau ci-dessus, j'ai essayé de changer le nombre de tâches et d'observer la mémoire consommée à la fin de tout calcul et avant join
- _ pool
. Les options 'del' et 'without del' permettent de supprimer ou de commenter la ligne del l
À l'intérieur de la fonction calculate(num)
respectivement. Avant calcul, la consommation mémoire est d'environ 4400.
J'ai un processus qui est basé sur cet exemple et est destiné à fonctionner à long terme. J'observe que ce processus de travail accapare beaucoup de mémoire (~ 4 Go) après une course de nuit. Faire un join
pour libérer de la mémoire n'est pas une option et j'essaie de trouver un moyen sans join
-.
Cela semble un peu mystérieux. Quelqu'un a-t-il rencontré quelque chose de similaire? Comment puis-je résoudre ce problème?
J'ai fait beaucoup de recherches et je n'ai pas trouvé de solution pour résoudre le problème en soi. Mais il existe un travail décent qui empêche l'éclatement de la mémoire pour un petit coût, en particulier du côté du code à exécution longue côté serveur.
La solution consistait essentiellement à redémarrer les processus de travail individuels après un nombre fixe de tâches. La classe Pool
dans python prend maxtasksperchild
comme argument. Vous pouvez spécifier maxtasksperchild=1000
limitant ainsi 1 000 tâches à exécuter sur chaque processus enfant. Après avoir atteint le nombre maxtasksperchild
, le pool actualise ses processus enfants. En utilisant un nombre prudent pour les tâches maximales, on peut équilibrer la mémoire maximale consommée, avec le coût de démarrage associé au redémarrage du processus principal. La construction Pool
se fait comme suit:
pool = mp.Pool(processes=2,maxtasksperchild=1000)
Je mets ici ma solution complète pour qu'elle puisse être utile aux autres!
import multiprocessing as mp
import time
def calculate(num):
l = [num*num for num in range(num)]
s = sum(l)
del l # delete lists as an option
return s
if __== "__main__":
# fix is in the following line #
pool = mp.Pool(processes=2,maxtasksperchild=1000)
time.sleep(5)
print "launching calculation"
num_tasks = 1000
tasks = [pool.apply_async(calculate,(i,)) for i in range(num_tasks)]
for f in tasks:
print f.get(5)
print "calculation finished"
time.sleep(10)
print "closing pool"
pool.close()
print "closed pool"
print "joining pool"
pool.join()
print "joined pool"
time.sleep(5)