2009-03-06 7 views
7

Sur mon 64 bits Debian/système Lenny (4 Gbytes RAM + 4 Gbytes partition de swap) Je peux faire avec succès:Existe-t-il un moyen de réduire la précision scipy/numpy pour réduire la consommation de mémoire?

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

mais avec f étant un np.complex128 la consommation de mémoire est choquant, et je ne peux pas faire grand-chose plus avec le résultat (par exemple, moduler les coefficients, puis f=ifftn(f)) sans traceback MemoryError. Plutôt que d'installer plus de RAM et/ou d'étendre mes partitions de swap, existe-t-il un moyen de contrôler la "précision par défaut" de scipy/numpy et de lui faire calculer un tableau complex64 à la place?

Je sais que je peux juste le réduire par la suite avec f=array(f,dtype=np.complex64); Je cherche à faire en sorte que la FFT fonctionne en précision 32 bits et en mémoire.

Répondre

5

Il semble qu'il n'y ait aucune fonction pour faire cela dans les fonctions fft de scipy (voir http://www.astro.rug.nl/efidad/scipy.fftpack.basic.html).

À moins que vous ne puissiez trouver une bibliothèque FFT à point fixe pour python, il est peu probable que la fonction que vous recherchez existe, car votre format de matériel flottant natif est de 128 bits. Il semble que vous pourriez utiliser la méthode rfft pour obtenir uniquement les composants à valeur réelle (pas de phase) de la FFT, et cela permettrait d'économiser la moitié de votre RAM.

Je courais le suivant en python interactif:

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

À ce stade, le RSS (Resident Set Size) de python était 265MB.

f = fft.fft(v) 

Et à ce stade le RSS de python 2.3GB.

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

Et à ce stade, le RSS descend à 2.0GB, depuis que je suis free'd jusqu'à v.

aide « fft.rfft (v) » pour calculer les valeurs réelles que des résultats en un RSS de 1,3 Go. (Près de la moitié, comme prévu)

pratique:

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

est le pire des deux mondes, car il calcule d'abord la version complex128 (2.3GB) puis copies dans la version complex64 (1.3GB) ce qui signifie que le pic RSS sur ma machine était de 3,6 Go, puis il s'est stabilisé à 1,3 Go à nouveau.

Je pense que si vous avez 4 Go de RAM, tout devrait fonctionner correctement (comme pour moi). Quel est le problème?

+1

Merci pour le pointeur sur les fonctions rfftn; oui ceux qui font le travail bien. L'utilisation maximale pour f = rfftn (v), f = array (f, dtype = np.complex64), f = irfftn (f) est 6224MByte dans l'inverse. (Sans le casting intermédiaire à complex64, il utilise 7754MByte ... un peu serré). – timday

+0

Votre taille de tableau de production est-elle réellement supérieure à 512^3? Je ne suis pas sûr pourquoi vous voyez quelque chose comme 4x l'utilisation de la RAM que je vois dans mon exemple de code ci-dessus ... – slacy

+0

Veuillez réviser le bit où vous dites que «la précision unique n'existe pas puisque votre matériel natif est de 128 bits». Le matériel natif n'est plus 128 bits que 64 bits, et FFTW est très flexible pour supporter les deux. Comme la réponse de David l'indique, 'scipy.fftpack.rfft' supporte ceci:' scipy.fftpack.rfft (v.astype (np.float32)) .dtype' renvoie 'float32'. Malheureusement, le soutien de Numpy est à la traîne de Scipy's, même en 2015: https://github.com/numpy/numpy/issues/6012 –

4

Scipy 0.8 aura un support de précision unique pour presque tout le code fft (Le code est déjà dans le coffre, donc vous pouvez installer scipy depuis svn si vous avez besoin de la fonctionnalité maintenant).

Questions connexes