2009-03-06 13 views
7

Auf meinem 64-Bit Debian/Lenny-System (4 GByte RAM + 4 GByte Swap-Partition) I erfolgreich tun können:Gibt es eine Möglichkeit, die Genauigkeit zu reduzieren, um den Speicherverbrauch zu reduzieren?

v=array(10000*random([512,512,512]),dtype=np.int16) 
f=fftn(v) 

aber mit f ist ein np.complex128 der Speicherverbrauch ist schockierend, und ich kann nicht viel tun, mehr mit dem Ergebnis (zB modulieren die Koeffizienten und dann f=ifftn(f)) ohne eine MemoryError Traceback.

Anstatt einige mehr RAM zu installieren und/oder meine Swap-Partitionen zu erweitern, gibt es eine Möglichkeit, die scipy/numpy "Standard-Präzision" zu steuern und stattdessen ein complex64-Array zu berechnen?

Ich weiß, ich kann es nur später mit f=array(f,dtype=np.complex64) reduzieren; Ich möchte die FFT tatsächlich mit 32-Bit-Präzision und halber Speicherkapazität arbeiten lassen.

Antwort

5

Es sieht nicht so aus, als ob es eine Funktion gibt, dies in scipys fft-Funktionen zu tun (siehe http://www.astro.rug.nl/efidad/scipy.fftpack.basic.html).

Sofern Sie keine Fixed-Point-FFT-Bibliothek für Python finden können, ist es unwahrscheinlich, dass die gewünschte Funktion existiert, da Ihr natives Hardware-Gleitkommaformat 128 Bit hat. Es sieht so aus, als könnten Sie die rfft-Methode verwenden, um nur die reellwertigen Komponenten (keine Phase) der FFT zu erhalten, und das würde die Hälfte Ihres RAMs einsparen.

lief ich folgend in der interaktiven Python:

>>> from numpy import * 
>>> v = array(10000*random.random([512,512,512]),dtype=int16) 
>>> shape(v) 
(512, 512, 512) 
>>> type(v[0,0,0]) 
<type 'numpy.int16'> 

An diesem Punkt die RSS (Resident Set Size) von Python 265MB war.

f = fft.fft(v) 

Und an dieser Stelle der RSS von Python 2.3GB.

>>> type(f) 
<type 'numpy.ndarray'> 
>>> type(f[0,0,0]) 
<type 'numpy.complex128'> 
>>> v = [] 

Und an dieser Stelle die RSS zu 2.0GB geht, da ich v free'd up haben.

Mit "fft.rfft (v)" real-Werte zu berechnen, führt nur in ein 1.3GB RSS. (Fast die Hälfte, wie erwartet)

tun:

>>> f = complex64(fft.fft(v)) 

Ist das Schlimmste aus beiden Welten, da sie zunächst die complex128 Version (2,3 GB) berechnet und dann Kopien, die in die complex64 Version (1,3 GB) was bedeutet, dass der Spitzen-RSS auf meinem Rechner 3,6 GB betrug und dann wieder auf 1,3 GB gesunken ist.

Ich denke, dass wenn Sie 4GB RAM haben, sollte dies alles gut funktionieren (wie es für mich tut). Was ist das Problem?

+1

Danke für den Zeiger auf die Funktionen rfftn; Ja, die machen das gut. Peak-Nutzung für f = rfftn (v), f = Array (f, dtype = np.complex64), f = irfftn (f) ist 6224MByte in der inversen. (Ohne das intermediate Cast zu complex64 verwendet es 7754MByte ... ein bisschen knapp). – timday

+0

Ist Ihre Produktions-Array-Größe tatsächlich größer als 512^3? Ich bin nicht sicher, warum Sie etwas wie 4x die RAM-Nutzung sehen, die ich in meinem obigen Beispielcode sehe ... – slacy

+0

Bitte überarbeiten Sie das Bit, wo Sie sagen: "Single-Precision existiert nicht, da Ihre native Hardware 128-Bit ist" - native Hardware ist nicht mehr 128 Bit als 64 Bit, und FFTW ist sehr flexibel bei der Unterstützung beider. Wie die Antwort von David zeigt, unterstützt 'scipy.fftpack.rfft' folgendes:' scipy.fftpack.rfft (v.astype (np.float32)) .dtype gibt 'float32' zurück. Leider hinkt die Unterstützung von Numpy selbst im Jahr 2015 hinter Scipy zurück: https://github.com/numpy/numpy/issues/6012 –

4

Scipy 0.8 wird für fast alle fft-codes über eine einzige Genauigkeitsunterstützung verfügen (Der Code ist bereits im Trunk, so dass Sie scipy von svn installieren können, wenn Sie die Funktion jetzt benötigen).