FFT output is blank when using FFTW_MEASURE, but works fine with FFTW_ESTIMATE
Asked Answered
H

1

6

I'm having the following issue in my attempt to use fftw3. For some reason, whenever I do an FFT using FFTW_MEASURE instead of FFTW_ESTIMATE, I get blank output. Ultimately I'm trying to implement fft convolution, so my example below includes both the FFT and the inverse FFT.

Clearly I'm missing something... is anyone able to educate me? Thank you!

I'm on Linux (OpenSUSE Leap 42.1), using the version of fftw3 available from my package manager.

Minimum working example:

#include <iostream>
#include <iomanip>
#include <cmath>
#include <fftw3.h>
using namespace std;


int main(int argc, char ** argv)
{
    int width = 10;    
    int height = 8;

    cout.setf(ios::fixed|ios::showpoint);
    cout << setprecision(2);

    double * inp = (double *) fftw_malloc(sizeof(double) * width * height);
    fftw_complex * cplx = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * height * (width/2 + 1));

    for(int i = 0; i < width * height; i++) inp[i] = sin(i);

    fftw_plan fft = fftw_plan_dft_r2c_2d(height, width, inp, cplx,  FFTW_MEASURE );
    fftw_plan ifft = fftw_plan_dft_c2r_2d(height, width, cplx, inp,  FFTW_MEASURE );

    fftw_execute(fft);

    for(int j = 0; j < height; j++)
    {
        for(int i = 0; i < (width/2 + 1); i++)
        {
            cout << cplx[i+width*j][0] << " ";
        }
        cout << endl;
    }
    cout << endl << endl;

    fftw_execute(ifft);

    for(int j = 0; j < height; j++)
    {
        for(int i = 0; i < width; i++)
        {
            cout << inp[i+width*j] << " ";
        }
        cout << endl;
    }

    fftw_destroy_plan(fft);
    fftw_destroy_plan(ifft);
    fftw_free(cplx);
    fftw_free(inp);

    return 0;
}

Just change between FFTW_ESTIMATE and FFTW_MEASURE.

Compiled with:

g++ *.cpp -lm -lfftw3 --std=c++11

Output with FFTW_ESTIMATE (first block is the real part of the FT, second block is after inverse FT):

1.51 2.24 -1.52 -0.05 0.15 0.19 
0.23 0.15 1.77 1.19 0.54 0.41 
1.97 -0.15 -1.32 -2.51 -1.20 -3.38 
4.34 15.21 -24.82 -7.44 -4.16 -2.51 
-0.43 -0.06 1.55 2.93 -2.81 -0.42 
0.00 0.00 0.00 -nan 0.00 0.00 
0.00 0.00 0.00 0.00 0.00 -nan 
0.00 0.00 0.00 0.00 0.00 0.00 


0.00 67.32 72.74 11.29 -60.54 -76.71 -22.35 52.56 79.15 32.97 
-43.52 -80.00 -42.93 33.61 79.25 52.02 -23.03 -76.91 -60.08 11.99 
73.04 66.93 -0.71 -67.70 -72.45 -10.59 61.00 76.51 21.67 -53.09 
-79.04 -32.32 44.11 79.99 42.33 -34.25 -79.34 -51.48 23.71 77.10 
59.61 -12.69 -73.32 -66.54 1.42 68.07 72.14 9.89 -61.46 -76.30 
-20.99 53.62 78.93 31.67 -44.70 -79.98 -41.72 34.89 79.43 50.94 
-24.38 -77.29 -59.13 13.39 73.60 66.15 -2.12 -68.44 -71.83 -9.18 
61.91 76.08 20.31 -54.14 -78.81 -31.02 45.29 79.96 41.12 -35.53

Output with FFTW_MEASURE (first block is the real part of the FT, second block is after inverse FT):

0.00 0.00 0.00 0.00 0.00 0.00 
0.00 0.00 0.00 0.00 0.00 0.00 
0.00 0.00 0.00 0.00 0.00 0.00 
0.00 0.00 0.00 0.00 0.00 0.00 
0.00 0.00 0.00 0.00 0.00 0.00 
0.00 0.00 0.00 -nan 0.00 0.00 
0.00 0.00 0.00 0.00 0.00 -nan 
0.00 0.00 0.00 0.00 0.00 0.00 


0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 
0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 
0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 
0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 
0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 
0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 
0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 
0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
Hangdog answered 11/12, 2015 at 17:55 Comment(1)
You need to initialise the input data after you create the plans, not before, otherwise it will get wiped out during plan creation as FFTW tests different butterflies etc.Tremann
C
3

The comment of @Paul_R. is sufficient to solve the problem. The input array can be modified as fftw_plan_dft_r2c_2d() is called. Hence, the input array must be initialized after the creation of the fftw plan.

The documentation of the planner flags of FFTW details what is happening. I am pretty sure that you have already guessed the reason why FFTW_ESTIMATE preserve the input array and FTTW_MEASURE modifies it.

Important: the planner overwrites the input array during planning unless a saved plan (see Wisdom) is available for that problem, so you should initialize your input data after creating the plan.*** The only exceptions to this are the FFTW_ESTIMATE and FFTW_WISDOM_ONLY flags, as mentioned below.

...

  • FFTW_ESTIMATE specifies that, instead of actual measurements of different algorithms, a simple heuristic is used to pick a (probably sub-optimal) plan quickly. With this flag, the input/output arrays are not overwritten during planning.
  • FFTW_MEASURE tells FFTW to find an optimized plan by actually computing several FFTs and measuring their execution time. Depending on your machine, this can take some time (often a few seconds). FFTW_MEASURE is the default planning option.

...

The documentation also tells us that the flag FFTW_ESTIMATE will preserve the input. Yet, the best advise is to initialize the array once the plan is created.

Crowns answered 26/12, 2015 at 21:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.