pythonfftfftwpyfftw

Using FFTW Wisdom in pyFFTW for optimized Fast Fourier Transforms


I am working on a project that involves performing FFTs on large datasets using the pyFFTW library in Python. I've heard that FFTW has a feature called "wisdom" that can significantly improve the performance of FFT computations by precomputing optimal plans for specific transform sizes and configurations.

I am not entirely sure how to effectively use this wisdom feature within the pyFFTW library. I've read the documentation, but I'm still a bit confused about the practical implementation. I would appreciate any insights into when and how to apply the wisdom to my FFT computations for the best performance gains.

Here's a MWE of the setup I am working with:

import pyfftw

# Define input and output data arrays
input_data = pyfftw.empty_aligned(128, dtype='complex128')
output_data = pyfftw.empty_aligned(128, dtype='complex128')

# Create an FFT object using pyFFTW
fft_object = pyfftw.FFTW(input_data, output_data, direction='FFTW_FORWARD', flags=('FFTW_MEASURE',))

# Perform FFT computation
fft_object(input_data)

Solution

  • "Wisdom" in the FFTW library refers to precomputed information about optimal plans for FFT computations.

    Upon the initialization of an FFT object, a planning process takes place, during which wisdom is stored. As a consequence, the resulting FFT object is finely tuned to the specific shape and type of the provided input data. Subsequent transformations employing this planning will automatically reuse of the stored wisdom.

    Hence, all the wisdom magics are handled internally. Exporting wisdom becomes relevant when desiring to employ a specific planning knowledge instead of recalculating it. As an example, consider a scenario where a subsequent computing session reuses the previously exported wisdom:

    1. First session; planning is computed, and the resulting wisdom is exported:

      import pyfftw
      
      # Define input and output data arrays
      input_data = pyfftw.empty_aligned(128, dtype='complex128')
      output_data = pyfftw.empty_aligned(128, dtype='complex128')
      
      # Create an FFT object with pyFFTW
      fft_object = pyfftw.FFTW(
          input_data,
          output_data,
          direction='FFTW_FORWARD',
          flags=('FFTW_MEASURE',),
      )
      
      # Perform FFT computation (this will compute and store internally the wisdom)
      fft_object(input_data)
      
      # Export the computed wisdom to a file
      pyfftw.export_wisdom(filename='./fft_wisdom.dat')
      
    2. Second session; the exported wisdom is loaded to speedup the optimization process:

      import pyfftw
      
      # Define input and output data arrays
      input_data = pyfftw.empty_aligned(128, dtype='complex128')
      output_data = pyfftw.empty_aligned(128, dtype='complex128')
      
      # Load wisdom from file
      pyfftw.import_wisdom(filename='./fft_wisdom.dat')
      
      # Create an FFT object using the loaded wisdom
      fft_object = pyfftw.FFTW(
          input_data,
          output_data,
          direction='FFTW_FORWARD',
          flags=('FFTW_MEASURE',),
      )
      
      # Perform FFT computation using planning wisdom
      fft_object(input_data)