Ich muss Datendateien iterativ lesen und die Daten in (numpy) Arrays speichern. Ich entschied mich, die Daten in ein Wörterbuch von "Datenfeldern" zu speichern: {'field1': array1, 'field2': array2, ...}.
Wenn Sie lists (oder collections.deque () ) zum Anhängen neuer Datenfelder verwenden, ist der Code effizient . Aber wenn ich die in den Listen gespeicherten Arrays verkette, wächst der Speicher und ich habe es nicht geschafft, ihn wieder freizugeben. Beispiel:
%Vor% Rechenzeit : 63,4 s
Speicherbelegung (oben): 13862 gime_se 20 0 1042m 934m 4148 S 0 5.8 1: 00.44 Python
Wenn Sie die numpy arrays bei jedem Aufruf direkt miteinander verknüpfen, ist ineffizient , Speicher bleibt jedoch unter Kontrolle . Beispiel:
%Vor% Rechenzeit : 1377.8 s
Speicherbelegung (oben): 14850 gime_se 20 0 650m 542m 4144 S 0 3.4 22: 31.21 Python
Gibt es eine Möglichkeit, die Leistung von Fall 1 zu nutzen, aber den Speicher unter Kontrolle zu halten, wie in Fall 2 ?
Es scheint, dass in Fall 1 der Speicher beim Verketten von Listenmitgliedern wächst (np.concatenate (value, axis = 0)). Bessere Ideen, es zu tun?
Hier ist was passiert, basierend auf was ich beobachtet habe. Es gibt nicht wirklich ein Speicherleck. Stattdessen entscheidet der Speicherverwaltungscode von Python (möglicherweise in Verbindung mit der Speicherverwaltung des Betriebssystems, in dem Sie sich befinden), den vom ursprünglichen Wörterbuch (das ohne die verketteten Arrays) belegten Speicherplatz im Programm zu belassen. Es ist jedoch frei, wiederverwendet zu werden. Ich habe dies bewiesen, indem ich Folgendes getan habe:
Wenn ich das tue, stelle ich fest, dass die Menge des verwendeten Speichers nur von ~ 900 GB auf ~ 1,3 GB gestiegen ist. Ohne den zusätzlichen Dictionary-Speicher sollten die Numpy-Daten selbst nach meinen Berechnungen etwa 427 MB beanspruchen, das summiert sich also. Das zweite, nicht verkettete Wörterbuch, das von unserer Funktion erstellt wurde, verwendete nur den bereits zugewiesenen Speicher.
Wenn Sie wirklich nicht mehr als ~ 600 MB Speicher verwenden können, dann würde ich Ihnen empfehlen, mit Ihren Numpy-Arrays etwas zu tun, was intern mit Python-Listen gemacht wird: Sie ordnen ein Array mit einer bestimmten Anzahl von Spalten zu. Ich habe diese verwendet, ein vergrößertes Array mit mehreren Spalten erstellt und die Daten kopiert. Dies reduziert die Anzahl der Verkettungen, was bedeutet, dass es schneller ist (aber immer noch nicht so schnell wie Listen), während der Speicherverbrauch niedrig bleibt. Natürlich ist es auch mühsam zu implementieren.
Ein einfacheres Beispiel, das das Wachstum der Speichernutzung reproduziert:
%Vor%Speichernutzung (oben): 24753 gime_se 20 0 1056m 948m 4104 S 0 5.9 0: 02.72 Python.
Nach dem Löschen der erstellten Objekte:
%Vor%Immer noch:
Speichernutzung (oben): 24753 gime_se 20 0 628m 520m 4128 S 0 3.2 0: 02.76 Python
Ist es möglich, diesen Speicher freizugeben?
Ich habe den Code noch mehr vereinfacht, indem ich nur Listen und Nummernfelder verwendet habe:
%Vor% was ungefähr doppelt so groß ist wie b = np.bereich (100000000.) (~ 800M). Nach del a
und del b
sinkt der verwendete Speicher auf ~ 800M. Wie von Justin Peel gezeigt, behält Python den Speicher der gelöschten Liste bei, aber dieser Speicher ist wiederverwendbar: Wenn der gleiche Code zweimal ausgeführt wird, wird dieselbe Speichermenge verbraucht wie nur einmal. Was auch immer passiert, es hat mit der Verkettung von Listenelementen zu tun. Gibt es eine Idee, wie der Speicherplatz freigegeben werden soll, der der gelöschten Liste zugewiesen wurde? Ist es möglich?
Tags und Links python performance memory-management