2009-03-06 13 views
7

En mi sistema Debian/Lenny 64 bits (partición de intercambio 4Gbyte RAM + 4Gbyte) que puedo hacer con éxito:¿Hay alguna forma de reducir la precisión scipy/numpy para reducir el consumo de memoria?

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

pero con f ser un np.complex128 el consumo de memoria es impactante, y no puedo hacer mucho más con el resultado (por ejemplo, modula los coeficientes y luego f=ifftn(f)) sin un seguimiento de MemoryError.

En lugar de instalar más RAM y/o expandir mis particiones de intercambio, ¿hay alguna manera de controlar la "precisión predeterminada" scipy/numpy y hacer que calcule una matriz complex64 en su lugar?

Sé que puedo reducirlo después con f=array(f,dtype=np.complex64); Estoy buscando que realmente haga el trabajo FFT con precisión de 32 bits y la mitad de la memoria.

Respuesta

5

Parece que no hay ninguna función para hacer esto en las funciones fft de scipy (consulte http://www.astro.rug.nl/efidad/scipy.fftpack.basic.html).

A menos que sea capaz de encontrar una biblioteca FFT de punto fijo para python, es poco probable que exista la función que desea, ya que su formato de punto flotante de hardware nativo es de 128 bits. Parece que podrías usar el método rfft para obtener solo los componentes de valor real (sin fase) de la FFT, y eso ahorraría la mitad de tu RAM.

Me corrió el siguiente en Python interactivo:

>>> 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'> 

En este punto el RSS (tamaño del conjunto residente) de pitón era 265MB.

f = fft.fft(v) 

Y en este punto el RSS de python 2.3GB.

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

Y en este punto el flujo se reduce a 2,0 GB, ya que he free'd hasta v.

El uso de "fft.rfft (v)" para calcular los valores reales sólo se traduce en un RSS de 1.3GB. (Casi la mitad, como era de esperar)

haciendo:

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

es el peor de ambos mundos, ya que calcula en primer lugar la versión complex128 (2.3 GB) y luego copia que en la versión complex64 (1,3 GB) lo que significa que el pico de RSS en mi máquina fue de 3.6GB, y luego se estableció en 1.3GB nuevamente.

Creo que si tienes 4GB de RAM, todo debería funcionar bien (como lo hace para mí). ¿Cual es el problema?

+1

Gracias por el puntero a las funciones de rfftn; sí, esos hacen bien el trabajo. Uso máximo para f = rfftn (v), f = array (f, dtype = np.complex64), f = irfftn (f) es 6224MByte en el inverso. (Sin el molde intermedio para complex64 usa 7754MByte ... un poco ajustado). – timday

+0

¿Su tamaño de matriz de producción es realmente mayor que 512^3? No estoy seguro de por qué estás viendo algo así como 4 veces el uso de RAM que veo en mi código de ejemplo anterior ... – slacy

+0

Revise el bit donde dice que "la precisión única no existe porque su hardware nativo es de 128 bits". El hardware nativo no tiene más de 128 bits que 64 bits, y FFTW es muy flexible para admitir ambos. Como indica la respuesta de David, 'scipy.fftpack.rfft' admite esto:' scipy.fftpack.rfft (v.astype (np.float32)). Dtype' devuelve 'float32'. Desafortunadamente, el soporte de Numpy va por detrás de Scipy's, incluso en 2015: https://github.com/numpy/numpy/issues/6012 –

4

Scipy 0.8 tendrá soporte de precisión única para casi todo el código fft (El código ya está en la línea externa, por lo que puede instalar scipy desde svn si necesita la función ahora).

Cuestiones relacionadas