使用FFTW_MEASURE时,FFT输出为空,但使用FFTW_ESTIMATE时效果良好

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

本文关键字:FFTW ESTIMATE FFT MEASURE 输出 使用      更新时间:2023-10-16

我在尝试使用fftw3时遇到以下问题。出于某种原因,每当我使用FFTW_MEASURE而不是FFTW_ESTIMATE进行FFT时,我都会得到空白输出。最后,我试图实现fft卷积,所以下面的例子包括fft和逆fft。

很明显我错过了什么。。。有人能教我吗?非常感谢。

我使用的是Linux(OpenSUSE Leap 42.1),使用的是包管理器提供的fftw3版本。

最小工作示例:

#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;
}

只需在FFTW_ESTIMATE和FFTW_MEASURE之间切换即可。

编制单位:

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

输出FFTW_ESTIMATE(第一个块是FT的实部,第二个块在逆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

输出FFTW_MEASURE(第一个块是FT的实部,第二个块在逆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

@Paul_R的评论。足以解决问题。当调用fftw_plan_dft_r2c_2d()时,可以修改输入数组。因此,输入数组必须在创建fftw计划后初始化。

FFTW的规划师标志的文档详细说明了正在发生的事情。我相信你已经猜到了FFTW_ESTIMATE保留输入数组而FTTW_MEASURE修改它的原因

重要提示:除非保存的计划(请参阅智慧)可用于解决该问题,否则计划器会在计划期间覆盖输入数组,因此您应该在创建计划后初始化输入数据。***唯一的例外是FFTW_ESTIMATE和FFTW_Wisdom_only标志,如下所述。

  • FFTW_ESTIMATE规定,使用简单的启发式方法来快速选择(可能是次优)计划,而不是实际测量不同的算法使用此标志,在规划过程中不会覆盖输入/输出阵列
  • FFTW_MEASURE告诉FFTW通过实际计算几个FFT并测量它们的执行时间来找到优化的计划。根据您的机器,这可能需要一些时间(通常几秒钟)。FFTW_MEASURE是默认的计划选项

文档还告诉我们,标志FFTW_ESTIMATE将保留输入。然而,最好的建议是在创建计划后初始化数组。