Existe uma maneira de reduzir a precisão Scipy/Numpy para reduzir o consumo de memória?
-
05-07-2019 - |
Pergunta
No meu sistema Debian/Lenny de 64 bits (Partição de troca 4GBYTE RAM + 4GBYTE), posso fazer com sucesso:
v=array(10000*random([512,512,512]),dtype=np.int16)
f=fftn(v)
Mas com f sendo um np.complex128
O consumo de memória é chocante e não posso fazer muito mais com o resultado (por exemplo, modula os coeficientes e depois f=ifftn(f)
) sem a MemoryError
traceback.
Em vez de instalar um pouco mais de RAM e/ou expandir minhas partições de troca, existe alguma maneira de controlar a "precisão padrão" Scipy/Numpy e fazer com que ele calcule uma matriz complexa 64?
Eu sei que posso simplesmente reduzi -lo depois com f=array(f,dtype=np.complex64)
; Estou querendo fazer com que o FFT funcione com precisão de 32 bits e metade da memória.
Solução
Não parece que há alguma função para fazer isso nas funções FFT da Scipy (veja http://www.astro.rug.nl/efidad/scipy.fftpack.basic.html ).
A menos que você possa encontrar uma biblioteca FFT de ponto fixo para o Python, é improvável que a função que você deseja exista, pois o formato de ponto flutuante de hardware nativo é de 128 bits. Parece que você pode usar o método RFFT para obter apenas os componentes de valor real (sem fase) da FFT, e isso economizaria metade da sua RAM.
Eu corri o seguinte no Python interativo:
>>> 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'>
Neste ponto, o RSS (tamanho do conjunto residente) do Python era de 265 MB.
f = fft.fft(v)
E neste ponto o RSS do Python 2,3 GB.
>>> type(f)
<type 'numpy.ndarray'>
>>> type(f[0,0,0])
<type 'numpy.complex128'>
>>> v = []
E neste momento o RSS cai para 2,0 GB, já que eu liberei v.
O uso de "fft.rfft (v)" para calcular valores reais resulta apenas em um RSS de 1,3 GB. (quase metade, como esperado)
Fazendo:
>>> f = complex64(fft.fft(v))
É o pior dos dois mundos, pois primeiro calcula a versão Complex128 (2,3 GB) e depois copia isso na versão Complex64 (1,3 GB), o que significa que o pico de RSS na minha máquina era de 3,6 GB e depois se estabeleceu para 1,3 GB novamente.
Eu acho que se você tem 4 GB de RAM, tudo isso deve funcionar bem (como faz para mim). Qual é o problema?
Outras dicas
O Scipy 0.8 terá suporte de precisão única para quase todo o código FFT (o código já está no tronco, para que você possa instalar o SCIPY da SVN se precisar do recurso agora).