Numpy: Чрезвычайно долгое время выполнения в numpy.fft.fft (Trac # 1266)

Созданный на 19 окт. 2012  ·  19Комментарии  ·  Источник: numpy/numpy

_Оригинальный билет http://projects.scipy.org/numpy/ticket/1266 от 19 октября 2009 г. пользователем trac koehler, назначен unknown._

Хотя в документации numpy.fft.fft указано, что:
«Это наиболее эффективно для степени двойки. Здесь также хранится кеш рабочей памяти для различных размеров fft, поэтому теоретически вы можете столкнуться с проблемами памяти, если вызовете это слишком много раз со слишком большим количеством разных n». , Я думаю, что может быть важно сообщить об этой странности во время выполнения fft.
В зависимости от длины массива время выполнения fft сильно различается:

[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
00 - Bug numpy.fft

Самый полезный комментарий

Это должно быть исправлено в numpy 1.17.

Все 19 Комментарий

_ @ endolith написал (а) 2009-11-20_

По теме: # 1177 http://projects.scipy.org/scipy/ticket/949

_ @ rgommers написал (а) 2011-03-01_

_ @ rgommers написал (а) 2011-03-01_

Дэвид С. реализовал преобразование Блюстейна, если оно вам нужно: https://github.com/cournape/numpy/tree/bluestein

Надеюсь, скоро приземлится в багажник Numpy.

Milestone изменен на Unscheduled пользователем @mwiebe 25

в этом PR предлагается дополнение к маленьким простым числам
https://github.com/scipy/scipy/pull/3144
наличие функции для увеличения размера заполнения может быть полезной утилитой в numpys fftpack

Да, вместо m = 2 ** nextpow2(2 * n - 1) будет быстрее использовать что-то вроде функции next_regular

Я также столкнулся с этой проблемой, используя функцию detect_equilibration в pymbar, которая неоднократно вызывает np.fft и np.ifft через функцию автокорреляции statsmodels на многих все более коротких массивах. Я обнаружил профилирование кода, которое в конечном итоге привело меня к этой теме. Единственный обходной путь на данный момент - явный вызов

 np.fft.fftpack._fft_cache.clear()

чтобы не допустить опасного роста требований к памяти. Однако это не кажется идеальным решением. Было бы неплохо иметь либо kwarg, например "memsafe = True", и / или функцию для ручной очистки кеша без явной ссылки на глобальную переменную.

@juliantaylor Padding неприменим к простым БПФ, верно? Просто свертка / корреляция?

@rgommers Алгоритм https://github.com/scipy/scipy/issues/4288 , но требует предварительного вычисления сложных щебетаний и наиболее эффективен, когда вы сохраняете щебетать в памяти и многократно повторно использовать его для фрагментов данных. Так что я не уверен, подходит ли это для numpy и, может быть, просто отложите scipy.fftpack.czt для этого приложения?

В любом случае я думаю, что это можно закрыть как дубликат https://github.com/numpy/numpy/issues/1177 ? Разве что-то другое вроде алгоритма Рейдера лучше, чем у Блюстайна?

а проблема @smcantab другая?

@endolith это было давным-давно :) но да, теперь, когда я смотрю на это снова, это кажется другой проблемой. Проблема, о которой я сообщил, все еще может быть актуальной, и мне пришлось реализовать обходной путь, который я предложил в pymbar, чтобы она работала.

К вашему сведению, я столкнулся с кем-то на аудиоконференции, который показал мне этот пример. Легко воспроизвести и экстремально.

%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 длины 1e6: 16 МИЛЛИСекунд

fft длины 1e6 + 3: 1 МИНУТА 42 СЕКУНДА

Особенность, а не ошибка. FFTPACK является «быстрым» только тогда, когда размер множится как произведение чисел 2, 3, 4, 5. Давно было желание использовать более быстрый алгоритм для больших простых размеров, но он не был реализован. Обратите внимание, что 100003 - простое число.

Я бы не назвал это «особенностью», но это нормально, а не баг. :)

https://github.com/scipy/scipy/issues/4288 имеет алгоритм Bluestein, но для него требуется предварительное вычисление сложного щебета, поэтому необходимо провести некоторое тестирование, чтобы увидеть, при каких простых размерах он становится целесообразным.

Интересно. Главное, что я знаю, это то, что реализация fft по умолчанию для Julia и Matlab не имеет такого поведения. Мне любопытно, что делает реализация Julia, чтобы избежать такого поведения.

Юлия и Matlab называют FFTW, чего мы не можем сделать из-за его лицензии.

Обратите внимание, что есть привязки Python для FFTW; pyFFTW кажется довольно актуальным. Если скорость БПФ вызывает беспокойство, это, вероятно, выход. FFTPACK был хорошей реализацией для своего времени, но код и оборудование пошли дальше.

@charris Я определенно ценю информацию, и это прискорбно, но имеет смысл в отношении лицензии.

Это должно быть исправлено в numpy 1.17.

спасибо @mreineck , закрытие

Была ли эта страница полезной?
0 / 5 - 0 рейтинги