Optimierung der Speichernutzung in numpy

8

Das folgende Programm lädt zwei Bilder mit PyGame, konvertiert sie in Numpy-Arrays und führt dann einige andere Numpy-Operationen (z. B. FFT) durch, um ein Endergebnis (einiger Zahlen) zu erhalten. Die Eingaben können groß sein, aber zu jedem Zeitpunkt sollten nur ein oder zwei große Objekte aktiv sein.

Ein Testbild ist etwa 10 Millionen Pixel groß, was bei Graustufen 10 MB bedeutet. Es wird in ein Numpy-Array von dtype uint8 konvertiert, das nach einiger Verarbeitung (Anwendung von Hamming-Fenstern) ein Array von dtype float64 ist. Zwei Bilder werden auf diese Weise in Arrays geladen; später führen FFT-Schritte zu einem Array von dtype complex128 . Vor dem Hinzufügen der übermäßigen gc.collect -Aufrufe tendierte die Programmspeichergröße dazu, mit jedem Schritt zuzunehmen. Außerdem scheinen die meisten Numpy-Operationen ein Ergebnis mit der höchsten verfügbaren Präzision zu liefern.

Das Ausführen des Tests (ohne die gc.collect -Aufrufe) auf meiner 1 GB Linux-Maschine führt zu längerem Thrashing, auf das ich nicht gewartet habe. Ich habe noch keine detaillierten Speicherbenutzungsstatistiken - ich habe einige Python-Module und den Befehl time vergeblich versucht; jetzt schaue ich in valgrind. Das Überwachen von PS (und das Behandeln der Nichtansprechbarkeit des Computers in den späteren Phasen des Tests) schlägt eine maximale Speicherauslastung von ca. 800 MB vor.

Ein 10 Millionen-Zellen-Array von complex128 sollte 160 MB belegen. Wenn (idealerweise) höchstens zwei davon auf einmal leben, plus die nicht unerheblichen Python- und Numpy-Bibliotheken und andere Utensilien, bedeutet das vermutlich 500 MB.

Ich kann mir zwei Blickwinkel vorstellen, um das Problem anzugehen:

  • Verwerfen von Zwischen-Arrays so schnell wie möglich. Dafür sind die gc.collect -Aufrufe - sie scheinen die Situation verbessert zu haben, da sie nun mit nur ein paar Minuten des Thrashings abgeschlossen ist ;-). Ich denke, man kann erwarten, dass die speicherintensive Programmierung in einer Sprache wie Python einen manuellen Eingriff erfordert.

  • Verwenden Sie bei jedem Schritt weniger präzise Numpy-Arrays. Leider scheinen die Operationen, die Arrays zurückgeben, wie fft2 , den Typ nicht zu spezifizieren.

Meine Hauptfrage lautet also: Gibt es eine Möglichkeit, die Ausgabegenauigkeit in Numpy-Array-Operationen anzugeben?

Gibt es allgemein allgemeinere speichererhaltende Techniken bei der Verwendung von Numpy?

Zusätzlich, hat Numpy eine idiomatische Art, den Array-Speicher zu befreien? (Ich könnte mir vorstellen, dass das Array-Objekt in Python live bleibt, aber in einem unbrauchbaren Zustand.) Explizites Löschen gefolgt von sofortigem GC fühlt sich hacky an.

%Vor%     
Edmund 29.06.2010, 07:25
quelle

2 Antworten

1

Dies auf SO sagt "Scipy 0.8 wird Single-Precision-Unterstützung für fast alle FFT-Code haben", und SciPy 0.8.0 Beta 1 ist gerade out.
(Habe es nicht selbst versucht, feige.)

    
denis 29.06.2010, 15:16
quelle
1

Wenn ich richtig verstehe, berechnen Sie eine Faltung zwischen zwei Bildern. Das Scipy-Paket enthält ein dediziertes Modul ( ndimage ), das möglicherweise effizienter ist als der "manuelle" Ansatz über Fourier-Transformationen. Es wäre gut, es zu versuchen, anstatt durch Numpy zu gehen.

    
EOL 29.06.2010 08:14
quelle