Differences between FFTW and CUFFT output
Asked Answered
U

1

6

In the char I have posted below, I am comparing the results from an IFFT run in FFTW and CUFFT.

What are the possible reasons this is coming out different? Is it really THAT much round off error?

Here is the relevant code snippet:

cufftHandle plan;
cufftComplex *d_data;
cufftComplex *h_data;
cudaMalloc((void**)&d_data, sizeof(cufftComplex)*W);

complex<float> *temp = (complex<float>*)fftwf_malloc(sizeof(fftwf_complex) * W);
h_data = (cufftComplex *)malloc(sizeof(cufftComplex)*W);
memset(h_data, 0, W*sizeof(cufftComplex));

/* Create a 1D FFT plan. */
cufftPlan1d(&plan, W, CUFFT_C2C, 1);

if (!reader->getData(rowBuff, row))    
    return 0;

// copy from read buffer to our FFT input buffer    
memcpy(indata, rowBuff, fCols * sizeof(complex<float>));

for(int c = 0; c < W; c++)
    h_data[c] = make_cuComplex(indata[c].real(), indata[c].imag());

cutilSafeCall(cudaMemcpy(d_data, h_data, W* sizeof(cufftComplex), cudaMemcpyHostToDevice));
cufftExecC2C(plan, d_data, d_data, CUFFT_INVERSE);
cutilSafeCall(cudaMemcpy(h_data, d_data,W * sizeof(cufftComplex), cudaMemcpyDeviceToHost));

for(int c = 0; c < W; c++)
    temp[c] =(cuCrealf(h_data[c]), cuCimagf(h_data[c]));

//execute ifft plan on "indata"
fftwf_execute(ifft);
 ...
 //dump out abs() values of the first 50 temp and outdata values. Had to convert h_data back to a normal complex

ifft was defined like so:

ifft = fftwf_plan_dft_1d(freqCols, reinterpret_cast<fftwf_complex*>(indata),
                         reinterpret_cast<fftwf_complex*>(outdata), 
                         FFTW_BACKWARD, FFTW_ESTIMATE);

and to generate the graph I dumped out h_data and outdata after the fftw_execute W is the width of the row of the image I am processing.

See anything glaringly obvious?

enter image description here

Underhanded answered 9/3, 2011 at 16:30 Comment(7)
What are you plotting ? Real parts ? Moduli ?Arnica
Magnitude of the complex numbersUnderhanded
@Derek: How do you compute them? Did you try |a + bi| = |a| * (1 + (b/a)^2) if a > b, |b| * (1 + (a / b)^2) else ?Arnica
I just used the abs() function of the std::complex libraryUnderhanded
After creating a simple case, of just generating an array of numbers 1-50 and running the forward and backward FFT on them, I see that the CUFFT lib has a scaling factor of 1/sqrt(2). Any idea where this is coming from?Underhanded
So it looks like CUFFT is returning a real and imaginary part, and FFTW only the real. The cuCabsf() function that comes iwth the CUFFT complex library causes this to give me a multiple of sqrt(2) when I have both parts of the complexUnderhanded
@Derek: post this as an answer (and accept it) so that people seeing this question can know what it was about.Arnica
U
8

So it looks like CUFFT is returning a real and imaginary part, and FFTW only the real. The cuCabsf() function that comes iwth the CUFFT complex library causes this to give me a multiple of sqrt(2) when I have both parts of the complex

As an aside - I never have been able to get exactly matching results in the intermediate steps between FFTW and CUFFT. If you do both the IFFT and FFT though, you should get something close.

Underhanded answered 23/3, 2011 at 21:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.