Mejora del rendimiento de FFT en Python

¿Cuál es la implementación FFT más rápida en Python?

Parece que numpy.fft y scipy.fftpack se basan en fftpack y no en FFTW. ¿Es fftpack tan rápido como FFTW? ¿Qué pasa con el uso de FFT de multiproceso, o el uso de FFT distribuido (MPI)?

Sin duda, podría ajustar la implementación FFT que quisiera probar con Cython u otras herramientas afines que le permitan acceder a bibliotecas externas.

Basado en GPU

Si va a probar las implementaciones de FFT, también puede echar un vistazo a los códigos basados ​​en GPU (si tiene acceso al hardware adecuado). Hay varias: reikna.fft , scikits.cuda .

Basado en la CPU

También hay un envoltorio de python FFTW pyFFTW basado en CPU.

(También existe pyFFTW3 , pero no se mantiene tan activamente como pyFFTW, y no funciona con Python3. ( Fuente ))

No tengo experiencia con ninguno de estos. Probablemente le corresponderá investigar y comparar diferentes códigos para su aplicación en particular si la velocidad es importante para usted.

Para una prueba detallada en https://gist.github.com/fnielsen/99b981b9da34ae3d5035 encuentro que scipy.fftpack funciona bien en comparación con mi aplicación simple de pyfftw a través de pyfftw.interfaces.scipy_fftpack , excepto por datos con una longitud correspondiente a un primo número.

Parece que hay un cierto costo de instalación asociado con evocar pyfftw.interfaces.scipy_fftpack.fft la primera vez. La segunda vez es más rápido. El paquete de Fft de Numpy y Scipy con un número primo se desempeña terriblemente para el tamaño de los datos que probé. CZT es más rápido en ese caso. Hace algunos meses se presentó un problema en Github de Scipy’s sobre el problema, consulte 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 implementación. Dado que ambos envuelven la biblioteca FFTW3, creo que la velocidad debería ser la misma.

https://pypi.python.org/pypi/pyFFTW

Donde trabajo, algunos investigadores han comstackdo esta biblioteca de Fortran que configura y llama a la FFTW para un problema particular. Esta biblioteca de Fortran (módulo con algunas subrutinas) espera algunos datos de entrada (listas 2D) de mi progtwig Python.

Lo que hice fue crear una pequeña 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 (arrays), y una función “compute”.

Crear una extensión C 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.

El sitio de FFTW muestra que fftpack se ejecuta aproximadamente 1/3 tan rápido como FFTW, pero eso es un paso de Fortran-to-C traducido mecánicamente seguido de una comstackción de C, y no sé si numpy / scipy usa una comstackción de Fortran más directa. Si el rendimiento es crítico para usted, puede considerar comstackr FFTW en una biblioteca compartida / DLL y usar ctypes para acceder a él, o crear una extensión C personalizada.

FFTW3 parece ser la implementación más rápida disponible que está muy bien envuelta. Los enlaces de PyFFTW en la primera respuesta funcionan. Aquí hay un código que compara los tiempos de ejecución: test_ffts.py