Какая самая быстрая реализация БПФ в Python?
Кажется, что numpy.fft и scipy.fftpack основаны на fftpack, а не на FFTW. Является ли fftpack таким же быстрым, как FFTW? Как насчет использования многопоточного БПФ или распределенного (MPI) БПФ?
Какая самая быстрая реализация БПФ в Python?
Кажется, что numpy.fft и scipy.fftpack основаны на fftpack, а не на FFTW. Является ли fftpack таким же быстрым, как FFTW? Как насчет использования многопоточного БПФ или распределенного (MPI) БПФ?
Вы, безусловно, можете обернуть любую реализацию БПФ, которую хотите протестировать, используя Cython или другие аналогичные инструменты, которые позволяют вам получать доступ к внешним библиотекам.
Если вы собираетесь тестировать реализации БПФ, вы также можете взглянуть на коды на основе графического процессора (если у вас есть доступ к соответствующему оборудованию). Их несколько: reikna.fft, scikits.cuda.
Существует также оболочка Python FFTW на основе процессора pyFFTW.
(Существует также pyFFTW3, но он не так активно поддерживается, как pyFFTW, и не работать с Python3. (источник))
У меня нет опыта ни с одним из них. Вероятно, вам придется немного покопаться и сравнить различные коды для вашего конкретного приложения, если для вас важна скорость.
Для теста, подробно описанного на https://gist.github.com/fnielsen/99b981b9da34ae3d5035, я считаю, что scipy.fftpack работает нормально по сравнению с моим простым применением pyfftw через pyfftw.interfaces.scipy_fftpack
, за исключением данных с длиной, соответствующей простому числу.
Кажется, что есть некоторые затраты на установку, связанные с вызовом pyfftw.interfaces.scipy_fftpack.fft в первый раз. Второй раз быстрее. Fftpack Numpy и scipy с простым числом работает ужасно для размера данных, которые я пробовал. CZT в этом случае быстрее. Несколько месяцев назад на Github Scipy была опубликована проблема, см. https://github.com/scipy/scipy/issues/4288
20000 prime=False
padded_fft : 0.003116
numpy_fft : 0.003502
scipy_fft : 0.001538
czt : 0.035041
fftw_fft : 0.004007
------------------------------------------------------------
20011 prime=True
padded_fft : 0.001070
numpy_fft : 1.263672
scipy_fft : 0.875641
czt : 0.033139
fftw_fft : 0.009980
------------------------------------------------------------
21803 prime=True
padded_fft : 0.001076
numpy_fft : 1.510341
scipy_fft : 1.043572
czt : 0.035129
fftw_fft : 0.011463
------------------------------------------------------------
21804 prime=False
padded_fft : 0.001108
numpy_fft : 0.004672
scipy_fft : 0.001620
czt : 0.033854
fftw_fft : 0.005075
------------------------------------------------------------
21997 prime=True
padded_fft : 0.000940
numpy_fft : 1.534876
scipy_fft : 1.058001
czt : 0.034321
fftw_fft : 0.012839
------------------------------------------------------------
32768 prime=False
padded_fft : 0.001222
numpy_fft : 0.002410
scipy_fft : 0.000925
czt : 0.039275
fftw_fft : 0.005714
------------------------------------------------------------
Пакет pyFFTW3 уступает библиотеке pyFFTW, по крайней мере, с точки зрения реализации. Поскольку они оба обертывают библиотеку FFTW3, я думаю, скорость должна быть одинаковой.
https://pypi.python.org/pypi/pyFFTW
Там, где я работаю, некоторые исследователи скомпилировали эту библиотеку Fortran, которая настраивает и вызывает FFTW для конкретной проблемы. Эта библиотека Fortran (модуль с некоторыми подпрограммами) ожидает некоторых входных данных (двумерных списков) от моей программы Python.
Что я сделал, так это создал небольшое C-расширение для Python, обертывающее библиотеку Fortran, где я в основном вызываю «init» для настройки планировщика FFTW, а также другую функцию для подачи моих 2D-списков (массивов) и «вычисления». функция.
Создание C-расширений — небольшая задача, и для этой конкретной задачи существует множество хороших руководств.
Что хорошо в этом подходе, так это то, что мы получаем скорость... большую скорость. Единственный недостаток заключается в расширении C, где мы должны перебирать список Python и извлекать все данные Python в буфер памяти.
сайт FFTW показывает, что fftpack работает примерно в 1/3 раза быстрее, чем FFTW, но это с механически переведенным шагом Fortran-to-C, за которым следует компиляция C, и я не знаю, использует ли numpy/scipy более прямую компиляцию Fortran. Если для вас критична производительность, вы можете скомпилировать FFTW в DLL/общую библиотеку и использовать ctypes для доступа к ней или создать собственное расширение C.
FFTW3 кажется самой быстрой доступной реализацией, которая хорошо упакована. Привязки PyFFTW в первом ответе работают. Вот код, который сравнивает время выполнения: test_ffts.py а>