Python multiprocessing memory Nutzung
Habe ich geschrieben, dass ein Programm kann wie folgt zusammengefasst werden:
def loadHugeData():
#load it
return data
def processHugeData(data, res_queue):
for item in data:
#process it
res_queue.put(result)
res_queue.put("END")
def writeOutput(outFile, res_queue):
with open(outFile, 'w') as f
res=res_queue.get()
while res!='END':
f.write(res)
res=res_queue.get()
res_queue = multiprocessing.Queue()
if __name__ == '__main__':
data=loadHugeData()
p = multiprocessing.Process(target=writeOutput, args=(outFile, res_queue))
p.start()
processHugeData(data, res_queue)
p.join()
Dem eigentlichen code (vor allem writeOutput()
) ist viel komplizierter. writeOutput()
nur verwendet diese Werte, es dauert so seine Argumente (was bedeutet, es nicht auf data
)
Grundsätzlich lädt er einen riesigen Datensatz in den Speicher und verarbeitet Sie. Schreiben der Ausgabe ist delegiert, um einen sub-Prozess (schreibt es in mehrere Dateien tatsächlich und dies erfordert eine Menge Zeit).
Also jedes mal, wenn ein Datenelement verarbeitet, es ist an der sub-Prozess Trog res_queue die wiederum schreibt das Ergebnis in der benötigten Dateien.
Den sub-Prozess nicht zugreifen müssen, Lesen oder ändern die Daten geladen loadHugeData()
in keiner Weise. Der sub-Prozess nur nutzen muss, was der Hauptprozess sendet durch res_queue
. Und dies führt mich zu meinem problem und Frage.
Scheint es mir, dass der sub-Prozess wird es auf der Kopie der riesige Datensatz (bei der überprüfung der Arbeitsspeicher-Nutzung mit top
). Ist das wahr? Und wenn ja, dann wie kann ich vermeiden, dass die id (mit Doppel-Speicher im wesentlichen)?
Ich bin mit Python 2.6 und das Programm läuft auch auf linux.
- Können Sie umstrukturieren Ihrem code verwenden Sie Iteratoren statt laden alle, die loadHugeData in ? Es scheint, dass Sie könnte, wenn es, wie es scheint, lade - /Prozess - /enqueue/dequeue/schreiben
- Die "hugeData" ist leider eine tab-getrennte txt-Datei, die im Grunde mit einem sparse array. Und ich brauche "random access", um diese Daten basieren auf der Zeilennummer, die während der Verarbeitung. Daher laden in den Speicher (mit sparse-array-spezifische Optimierungen) macht die Verarbeitung wesentlich schneller.
- Es könnte sein, Massiv " over-engineering zu empfehlen, so etwas wie `beanstalkd um den Prozess der integration, aber es wäre interessant zu wissen, ob es geholfen/skaliert/durchgeführt. Wie üblich, die Probleme anderer Menschen sind immer mehr interessant.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den
multiprocessing
Modul ist effektiv auf der Grundlage derfork
system-Aufruf erzeugt eine Kopie des aktuellen Prozesses. Da laden Sie den riesigen Daten, bevor Siefork
(oder erstellen Sie diemultiprocessing.Process
), wird der Kind-Prozess erbt eine Kopie der Daten.Jedoch, wenn das Betriebssystem Sie laufen, implementiert COW (copy-on-write), es wird nur eine Kopie der Daten im physikalischen Speicher, es sei denn, Sie ändern die Daten in der parent-oder child-Prozess (Eltern und Kind teilen die gleichen physischen Speicherseiten, wenn auch in unterschiedlichen virtuellen Adressräumen); und selbst dann zusätzlichen Speicher werden nur zugewiesen werden, für die änderungen (in
pagesize
- Schritten).Können Sie diese situation vermeiden, indem Berufung
multiprocessing.Process
bevor Sie Ihren laden großer Datenmengen. Dann ist die zusätzliche Speicherzuordnungen, die nicht reflektiert werden, in der die child-Prozesse beim laden von Daten im Elternprozess.meminfo
auf Linux wird der Bericht korrekt wiepmap
auf Solaris; keine Ahnung von Windows aber nicht 🙂multiprocessing.Process
vor dem laden der Daten scheint das Problem gelöst. Ich werde inmeminfo
aswell.