Comparatively slow python numpy 3D Fourier Transformation

前端 未结 2 1954
执笔经年
执笔经年 2021-01-19 23:07

For my work I need to perform discrete fourier transformations (DFTs) on large images. In the current example I require a 3D FT for a 1921 x 512 x 512 image (along with 2D F

相关标签:
2条回答
  • 2021-01-19 23:36

    You could try FFT from Intel MKL (Math Kernel Library) which is faster than FFTW. Intel provides mkl-fft for Python which replaces numpy.fft. All that you need to do is type:

    pip install mkl-fft
    

    and run your program again, without any changes.

    Also, numpy 1.17 (soon to be released) will have new implementation of FFT:

    Replacement of the fftpack-based FFT module by the pocketfft library

    Both implementations have the same ancestor (Fortran77 FFTPACK by Paul N. Swarztrauber), but pocketfft contains additional modifications which improve both accuracy and performance in some circumstances. For FFT lengths containing large prime factors, pocketfft uses Bluestein’s algorithm, which maintains O(N log N) run time complexity instead of deteriorating towards O(N*N) for prime lengths. Also, accuracy for real-valued FFTs with near-prime lengths has improved and is on par with complex-valued FFTs.

    0 讨论(0)
  • 2021-01-19 23:45

    Yes, there is a chance that using FFTW through the interface pyfftw will reduce your computation time compared to numpy.fft or scipy.fftpack. The performances of these implementations of DFT algorithms can be compared in benchmarks such as this one : some interesting results are reported in Improving FFT performance in Python

    I suggest the following code for a test:

    import pyfftw
    import numpy
    import time
    import scipy
    
    f = pyfftw.n_byte_align_empty((127,512,512),16, dtype='complex128')
    #f = pyfftw.empty_aligned((33,128,128), dtype='complex128', n=16)
    f[:] = numpy.random.randn(*f.shape)
    
    # first call requires more time for plan creation
    # by default, pyfftw use FFTW_MEASURE for the plan creation, which means that many 3D dft are computed so as to choose the fastest algorithm.
    fftf=pyfftw.interfaces.numpy_fft.fftn(f)
    
    #help(pyfftw.interfaces)
    tas = time.time()
    fftf=pyfftw.interfaces.numpy_fft.fftn(f) # here the plan is applied, nothing else.
    tas = time.time()-tas
    print "3D FFT, pyfftw:", tas
    
    f = pyfftw.n_byte_align_empty((127,512,512),16, dtype='complex128')
    #f = pyfftw.empty_aligned((33,128,128), dtype='complex128', n=16)
    f[:] = numpy.random.randn(*f.shape)
    
    
    tas = time.time()
    fftf=numpy.fft.fftn(f)
    tas = time.time()-tas
    print "3D FFT, numpy:", tas
    
    tas = time.time()
    fftf=scipy.fftpack.fftn(f)
    tas = time.time()-tas
    print "3D FFT, scipy/fftpack:", tas
    
    # first call requires more time for plan creation
    # by default, pyfftw use FFTW_MEASURE for the plan creation, which means that many 3D dft are computed so as to choose the fastest algorithm.
    f = pyfftw.n_byte_align_empty((128,512,512),16, dtype='complex128')
    fftf=pyfftw.interfaces.numpy_fft.fftn(f)
    
    tas = time.time()
    fftf=pyfftw.interfaces.numpy_fft.fftn(f) # here the plan is applied, nothing else.
    tas = time.time()-tas
    print "3D padded FFT, pyfftw:", tas
    

    For a size of 127*512*512, on my modest computer, I got:

    3D FFT, pyfftw: 3.94130897522
    3D FFT, numpy: 16.0487070084
    3D FFT, scipy/fftpack: 19.001199007
    3D padded FFT, pyfftw: 2.55221295357
    

    So pyfftw is significantly faster than numpy.fft and scipy.fftpack. Using padding is even faster, but the thing that is computed is different.

    Lastly, pyfftw may seem slower at the first run due to the fact that it uses the flag FFTW_MEASURE according to the documentation. It's a good thing if and only if many DFTs of the same size are successively computed.

    0 讨论(0)
提交回复
热议问题