Mein Code (Teil eines genetischen Optimierungsalgorithmus) läuft ein paar Prozesse parallel, wartet auf alle von ihnen zu Ende, liest die Ausgabe und wiederholt dann mit einer anderen Eingabe. Alles hat gut funktioniert, als ich mit 60 Wiederholungen getestet habe. Da es funktionierte, habe ich eine realistischere Anzahl der Wiederholungen verwenden beschlossen, erhielt 200. ich diesen Fehler:Python kann keinen Speicher mit multiprocessing.pool zuweisen
File "/usr/lib/python2.7/threading.py", line 551, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 504, in run
self.__target(*self.__args, **self.__kwargs)
File "/usr/lib/python2.7/multiprocessing/pool.py", line 302, in _handle_workers
pool._maintain_pool()
File "/usr/lib/python2.7/multiprocessing/pool.py", line 206, in _maintain_pool
self._repopulate_pool()
File "/usr/lib/python2.7/multiprocessing/pool.py", line 199, in _repopulate_pool
w.start()
File "/usr/lib/python2.7/multiprocessing/process.py", line 130, in start
self._popen = Popen(self)
File "/usr/lib/python2.7/multiprocessing/forking.py", line 120, in __init__
self.pid = os.fork()
OSError: [Errno 12] Cannot allocate memory
Hier ein Ausschnitt aus meinem Code, der Pool verwendet:
def RunMany(inputs):
from multiprocessing import cpu_count, Pool
proc=inputs[0]
pool=Pool(processes = proc)
results=[]
for arg1 in inputs[1]:
for arg2 in inputs[2]:
for arg3 in inputs[3]:
results.append(pool.apply_async(RunOne, args=(arg1, arg2, arg3)))
casenum=0
datadict=dict()
for p in results:
#get results of simulation once it has finished
datadict[casenum]=p.get()
casenum+=1
return datadict
Die RunOne Funktion erstellt ein Objekt in der Klasse, die ich erstellt habe, verwendet ein rechenintensives Python-Paket, um ein Chemieproblem zu lösen, das etwa 30 Sekunden dauert, und gibt das Objekt mit der Ausgabe des Chemie-Solver zurück.
Also ruft mein Code RunMany in Serie, und RunMany ruft dann RunOne parallel auf. In meinen Tests habe ich RunOne mit 10 Prozessoren (der Computer hat 16) und einem Pool von 20 Aufrufen von RunOne aufgerufen. Mit anderen Worten, len (arg1) * len (arg2) * len (arg3) = 20. Alles hat gut funktioniert, als mein Code 60 Mal RunMany aufgerufen hat, aber ich hatte keinen Speicher mehr, als ich 200 Mal anrief.
Bedeutet dies, dass einige Prozesse nicht korrekt aufgeräumt werden? Habe ich ein Speicherleck? Wie kann ich feststellen, ob ich ein Speicherleck habe und wie ich die Ursache des Lecks herausfinden kann? Das einzige Element, das in meiner 200-Wiederholungsschleife wächst, ist eine Liste von Zahlen, die von 0 bis 200 zunimmt. Ich habe ein Wörterbuch mit Objekten aus einer benutzerdefinierten Klasse, die ich gebaut habe, aber es ist auf eine Länge begrenzt von 50 Einträgen - jedes Mal, wenn die Schleife ausgeführt wird, löscht sie ein Element aus dem Wörterbuch und ersetzt es durch ein anderes Element.
Edit: Hier ist ein Ausschnitt aus dem Code, den RunMany
for run in range(nruns):
#create inputs object for RunMany using genetic methods.
#Either use starting "population" or create "child" inputs from successful previous runs
datadict = RunMany(inputs)
sumsquare=0
for i in range(len(datadictsenk)): #input condition
sumsquare+=Compare(datadict[i],Target[i]) #compare result to target
with open(os.path.join(mainpath,'Outputs','output.txt'),'a') as f:
f.write('\t'.join([str(x) for x in [inputs.name, sumsquare]])+'\n')
Objective.append(sumsquare) #add sum of squares to list, to be plotted outside of loop
population[inputs]=sumsquare #add/update the model in the "population", using the inputs object as a key, and it's objective function as the value
if len(population)>initialpopulation:
population = PopulationReduction(population) #reduce the "population" by "killing" unfit "genes"
avgtime=(datetime.datetime.now()-starttime2)//(run+1)
remaining=(nruns-run-1)*avgtime
print(' Finished '+str(run+1)+'/' +str(nruns)+'. Elapsed: '+str(datetime.datetime.now().replace(microsecond=0)-starttime)+' Remaining: '+str(remaining)+' Finish at '+str((datetime.datetime.now()+remaining).replace(microsecond=0))+'~~~', end="\r")
Da es nun die „Ergebnisse“ in keinem Verhältnis wachsen sehr schnell gehen, und wenn das passiert - Sie werden über genügend Arbeitsspeicher ausgeführt, wie Sie nie geöffnet schließen Pool von Prozessen. –
Puciek: "Ergebnisse" hat höchstens 20 Einträge. Die RunMany-Funktion wird von meiner Hauptfunktion aufgerufen, und "Ergebnisse" ist lokal für die RunMany-Funktion. Kann es als lokale Variable nicht gelöscht werden, wenn RunMany beendet ist? Oder funktionieren Pools nicht so? – Jeff
Es soll so funktionieren, aber manchmal Python haben Probleme nach sich selbst aufräumen. Hier ein ähnliches Problem http://stackoverflow.com/questions/24564782/ways-to-free-memory-back-to-os-from-python/24564983#24564983 –