_Tíquete original http://projects.scipy.org/numpy/ticket/1266 em 19/10/2009 pelo usuário trac koehler, atribuído a desconhecido._
Embora a documentação de numpy.fft.fft afirme que:
"Isso é mais eficiente para uma potência de dois. Isso também armazena um cache de memória de trabalho para diferentes tamanhos de fft's, então você poderia teoricamente ter problemas de memória se chamar isso muitas vezes com muitos ns diferentes." , Acho que pode ser importante relatar essa estranheza no tempo de execução do fft.
Dependendo do comprimento do array, o tempo de execução fft varia muito:
[ipython shell, from numpy import *]
In [1]: %time fft.fft(zeros(119516))
CPU times: user 22.83 s, sys: 0.39 s, total: 23.23 s
Wall time: 23.53 s
In [3]: %time fft.fft(zeros(119517))
CPU times: user 36.33 s, sys: 0.08 s, total: 36.40 s
Wall time: 36.51 s
In [5]: %time fft.fft(zeros(119518))
CPU times: user 4.88 s, sys: 0.08 s, total: 4.96 s
Wall time: 5.02 s
In [7]: %time fft.fft(zeros(119519))
CPU times: user 0.45 s, sys: 0.00 s, total: 0.45 s
Wall time: 0.45 s
In [9]: %time fft.fft(zeros(119515))
CPU times: user 0.07 s, sys: 0.00 s, total: 0.08 s
Wall time: 0.08 s
In [11]: %time fft.fft(zeros(119514))
CPU times: user 15.84 s, sys: 0.06 s, total: 15.90 s
Wall time: 15.95 s
In [13]: %time fft.fft(zeros(119513))
CPU times: user 272.75 s, sys: 1.03 s, total: 273.78 s
Wall time: 275.63 s
_ @ endolith escreveu em 20/11/2009
Relacionado: # 1177 http://projects.scipy.org/scipy/ticket/949
_ @ rgommers escreveu em
_ @ rgommers escreveu em
David C. implementou a transformação Bluestein se você precisar: https://github.com/cournape/numpy/tree/bluestein
Devo pousar no baú Numpy em breve.
Marco alterado para Unscheduled
por @mwiebe em
neste primo é proposto um enchimento para pequenos primos
https://github.com/scipy/scipy/pull/3144
ter a função de obter um tamanho de preenchimento melhor pode ser um utilitário útil no numpys fftpack
Sim, em vez de m = 2 ** nextpow2(2 * n - 1)
será mais rápido usar algo como a função next_regular
Eu também encontrei esse problema usando a função detect_equilibration de pymbar que chama repetidamente np.fft e np.ifft por meio da função de autocorrelação de modelos de estatísticas em muitos arrays cada vez mais curtos. Eu descobri o perfil do código, o que acabou me levando a este tópico. A única solução até agora é chamar explicitamente
np.fft.fftpack._fft_cache.clear()
para ter certeza de que o requisito de memória não aumenta perigosamente. No entanto, esta não parece ser a solução ideal. Seria bom ter um kwarg como "memsafe = True" e / ou uma função para limpar manualmente o cache sem se referir explicitamente à variável global.
@juliantaylor O preenchimento não é aplicável a FFTs simples, correto? Apenas para convolução / correlação?
@rgommers O algoritmo Bluestein acelera o FFT para tamanhos primos, como feito em https://github.com/scipy/scipy/issues/4288 , mas requer pré-cálculo de chirps complexos e é mais eficiente quando você mantém o chirp na memória e reutilizá-lo repetidamente em blocos de dados. Portanto, não tenho certeza se isso é bom para numpy e talvez apenas adie para scipy.fftpack.czt para este aplicativo?
De qualquer forma, acho que isso pode ser fechado como uma duplicata de https://github.com/numpy/numpy/issues/1177 ? A menos que algo como o algoritmo de Rader seja melhor que o de Bluestein?
e o problema de @smcantab é diferente?
@endolith, isso foi há muito tempo :) mas sim, agora que olho novamente, parece um problema diferente. O problema que relatei ainda pode ser relevante e tive que implementar a solução alternativa que sugeri no pymbar para que funcionasse.
Para sua informação, encontrei alguém em uma audioconferência que me mostrou este exemplo. É fácil de reproduzir e extremo.
%time np.fft.fft( np.random.randn(100000) )
Wall time: 16 ms
Out[16]:
array([ 196.58599022 +0.j , -88.38483360 +89.2507627j ,
-166.72250316+339.27161306j, ..., 12.22959535 -64.01621313j,
-166.72250316-339.27161306j, -88.38483360 -89.2507627j ])
%time np.fft.fft( np.random.randn(100003) )
Wall time: 1min 42s
Out[17]:
array([ 13.36160617 +0.j , -314.86472577-340.44686425j,
-258.36716707-170.43805382j, ..., -21.18014704+441.3618185j ,
-258.36716707+170.43805382j, -314.86472577+340.44686425j])
fft de comprimento 1e6: 16 MILIsegundos
fft de comprimento 1e6 + 3: 1 MINUTO e 42 SEGUNDOS
Recurso, não um bug. FFTPACK só é "rápido" quando o tamanho é fatorado como produto dos números 2, 3, 4, 5. Há um desejo antigo de usar um algoritmo mais rápido para tamanhos primos grandes, mas ele não foi implementado. Observe que 100003 é primo.
Eu não chamaria de "recurso", mas é normal e não um bug. :)
https://github.com/scipy/scipy/issues/4288 tem o algoritmo de Bluestein, mas requer pré-cálculo de um chirp complexo, portanto, seria necessário fazer alguns testes para ver em quais tamanhos primos vale a pena.
Interessante. A principal coisa que sei é que a implementação padrão do fft para Julia e Matlab não tem esse comportamento. Estou curioso para saber o que a implementação de Julia faz para evitar esse comportamento.
Julia e Matlab ligam para FFTW, o que não podemos fazer por causa de sua licença.
Observe que existem ligações Python para FFTW; pyFFTW parece bastante atual. Se a velocidade do FFT for uma preocupação, provavelmente esse é o caminho a percorrer. O FFTPACK era uma boa implementação para sua época, mas o código e o hardware mudaram.
@charris Eu definitivamente aprecio a informação e isso é lamentável, mas faz sentido em relação à licença.
@standarddeviant Você também pode fazer um monkey-patch pyfftw sobre numpy / scipy para fazê-lo usar FFTW
Isso deve ser corrigido em 1.17 numpy.
obrigado @mreineck , fechando
Comentários muito úteis
Isso deve ser corrigido em 1.17 numpy.