Mejorando el rendimiento de FFT en Python
Pregunta
¿Cuál es la implementación FFT más rápida en Python?
Parece que numpy.fft y scipy.fftpack están basados en fftpack y no en FFTW.¿Es fftpack tan rápido como FFTW?¿Qué pasa con el uso de FFT multiproceso o el uso de FFT distribuida (MPI)?
Solución
Ciertamente, podría empaquetar cualquier implementación de FFT que quisiera probar usando Cython u otras herramientas similares que le permitan acceder a bibliotecas externas.
Basado en GPU
Si va a probar implementaciones de FFT, también puede echar un vistazo a los códigos basados en GPU (si tiene acceso al hardware adecuado).Hay varios: reikna.fft, scikits.cuda.
basado en CPU
También hay un contenedor FFTW de Python basado en CPU pyFFTW.
(Hay pyFFTW3 también, pero no se mantiene tan activamente como pyFFTW y no funciona con Python3.(fuente))
No tengo experiencia con ninguno de estos.Probablemente le corresponderá a usted investigar un poco y comparar diferentes códigos para su aplicación particular si la velocidad es importante para usted.
Otros consejos
Para una prueba detallada en https://gist.github.com/fnielsen/99b981b9da34ae3d5035 Encuentro que scipy.fftpack funciona bien en comparación con mi simple aplicación de pyfftw a través de pyfftw.interfaces.scipy_fftpack
, excepto los datos con una longitud correspondiente a un número primo.
Parece haber algún costo de configuración asociado con evocar pyfftw.interfaces.scipy_fftpack.fft la primera vez. La segunda vez es más rápida. El fftpack de Numpy y Scipy con un número primo funciona terriblemente para el tamaño de los datos que probé. CZT es más rápido en ese caso. Hace unos meses se presentó un problema en Github de Scipy sobre el problema, ver 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
------------------------------------------------------------
El paquete PYFFTW3 es inferior en comparación con la biblioteca PYFFTW, al menos en cuanto a la implementación. Dado que ambos envuelven la biblioteca FFTW3, supongo que la velocidad debería ser la misma.
Donde trabajo, algunos investigadores han compilado esta biblioteca Fortran que configura y llama al FFTW para un problema particular. Esta biblioteca Fortran (módulo con algunas subrutinas) espera algunos datos de entrada (listas 2D) de mi programa Python.
Lo que hice fue crear un poco de extensión C para Python envolviendo la biblioteca Fortran, donde básicamente llamo "init" para configurar un planificador FFTW y otra función para alimentar mis listas 2D (matrices) y una función de "cómputo".
Crear una C-Extensiones es una tarea pequeña, y hay muchos buenos tutoriales para esa tarea en particular.
Lo bueno de este enfoque es que obtenemos velocidad ... mucha velocidad. El único inconveniente está en la extensión C donde debemos iterar sobre la lista de Python y extraer todos los datos de Python en un búfer de memoria.
los Sitio FFTW Muestra FFTPack que se ejecuta aproximadamente 1/3 tan rápido como FFTW, pero eso es con un paso FORTRAN-TO C traducido mecánicamente seguido de compilación de C, y no sé si Numpy/SciPY usa una compilación de Fortran más directa. Si el rendimiento es fundamental para usted, puede considerar compilar FFTW en una biblioteca DLL/compartida y usar CTYPES para acceder a él, o construir una extensión C personalizada.
FFTW3 parece ser la implementación más rápida disponible que está bien envuelta. Los enlaces PyffTW en el primer trabajo de respuesta. Aquí hay algún código que compara los tiempos de ejecución: test_ffts.py