2016-04-22 11 views
0

Ich führe einen evolutionären Algorithmus, um Funktionen in einer separaten Simulationsumgebung (auch in Python geschrieben) zu optimieren. Die Simulationsumgebung selbst ist eine Python-Klasseninstanz und ist rechenintensiv (~ 4 Sekunden pro Lauf) und benötigt etwa 1 GB Speicher. Da ich in dieser Simulationsumgebung ungefähr hunderttausend verschiedene Funktionen erzeuge, muss ich einen Weg finden, so viel wie möglich von der Simulation offline zu nehmen.Wie vermeide ich Deepcopy von Python 2.7-Klasseninstanzen?

Was ich tun kann, ist vorberechnen die Mehrheit der Simulation (dh eine Instanz der Klasse initialisieren und dann einige Untermenge von Klassenfunktionen ausführen) und dann den Algorithmus für nur eine kleine Komponente (z. B. die einige wenige Funktionen innerhalb der Klasse). Dies reduziert im Allgemeinen die Auswertungszeit auf ~ 1 Sekunde, was die Laufzeit signifikant verbessert.

Jedes Mal, wenn eine neue Funktion in die Simulationsklasseninstanz übergeben wird, wird die Klasseninstanz durch die Funktion geändert (und beeinflusst somit das Ergebnis der nächsten Funktionsauswertung). Ich kann dies verhindern, indem ich vor jeder Auswertung eine Deepcopy der gesamten Klasseninstanz durchführe, die aber langsamer ist als jedes Mal die gesamte Simulation auszuführen.

Gibt es eine Möglichkeit zu vermeiden, Deepcopying der gesamten Klasse in jeder Phase, aber um das gleiche Ergebnis zu erhalten? Im Wesentlichen muss jede Funktionsbewertung an genau derselben Klasseninstanz durchgeführt werden.

Dank

Antwort

1

So stellt sich heraus, dass dieses Problem ein Problem mit Pythons Multiprocessing.Pool Klasse ist (die ich nicht erwähnt hatte, da ich dachte, dass es nicht Teil des Problems war). Jeder Mitarbeiter im Pool ist standardmäßig für die gesamte Dauer des Pools geöffnet. Alle Prozesse, die von einem einzelnen Worker ausgeführt werden, bleiben zu jeder Zeit im Speicher. Da an diese Worker eine einzelne Klasseninstanz übergeben wird, wird diese Klasseninstanz bei jeder Ausführung einer Lösung aktualisiert. Der einfachste Weg, dies zu lösen, ist die Verwendung des Arguments "maxtasksperchild" von Multiprocessing.Pool, um die Anzahl der Aufgaben zu begrenzen, die ein einzelner Arbeiter bewältigen kann, bevor er getötet wird, und stattdessen einen neuen hervorbringt. Wenn Sie diesen Wert auf 1 setzen, haben Sie alle meine Probleme gelöst.

0

Dadurch wird die Ausgabe Ihrer sich entwickelnden Klassen nicht direkt lösen, aber ich habe sehr gute Erfahrungen mit der Leistung cPickle für das Speichern von Klasseninstanzen hatte. Ich verwende es, um den Zustand von benutzerdefinierten Datenstrukturen zu speichern, die ziemlich groß sind, und Laden und Speichern sind sehr schnelle Operationen.

Verwandte Themen