11

我有一个以列为主(Fortran 风格)格式存储的二维数据数组,我想对每一进行 FFT 。我想避免转置数组(它不是方形的)。例如,我的数组

fftw_complex* data = new fftw_complex[21*256];

包含条目[r0_val0, r1_val0,..., r20_val0, r0_val1,...,r20_val255]

如果它是主要的,我可以fftw_plan_many_dft用来制定计划来解决阵列中的 21 个 FFT 中的每一个,例如:data[r0_val0, r0_val1,..., r0_val255, r1_val0,...,r20_val255]

int main() {
  int N = 256;
  int howmany = 21;
  fftw_complex* data = new fftw_complex[N*howmany];
  fftw_plan p;

  // this plan is OK
  p = fftw_plan_many_dft(1,&N,howmany,data,NULL,1,N,data,NULL,1,N,FFTW_FORWARD,FFTW_MEASURE);
  // do stuff...

  return 0;
}

根据文档(FFTW 手册的第 4.4.1 节),该函数的签名是

fftw_plan fftw_plan_many_dft(int rank, const int *n, int howmany,
                              fftw_complex *in, const int *inembed,
                              int istride, int idist,
                              fftw_complex *out, const int *onembed,
                              int ostride, int odist,
                              int sign, unsigned flags);

我应该能够使用strideanddist参数来设置索引。从我可以从文档中了解到,要转换的数组中的条目被索引为in + j*istride + k*idistwherej=0..n-1k=0..howmany-1. (我的数组是一维的,并且有howmany)。但是,以下代码会导致段。错误(编辑:步幅错误,请参阅下面的更新):

int main() {
  int N = 256;
  int howmany = 21;
  fftw_complex* data = new fftw_complex[N*howmany];
  fftw_plan p;

  // this call results in a seg. fault.
  p = fftw_plan_many_dft(1,&N,howmany,data,NULL,N,1,data,NULL,N,1,FFTW_FORWARD,FFTW_MEASURE);

  return 0;
}

更新:

我在选择步幅时出错了。正确的调用是(正确的步幅是howmany,不是N):

int main() {
  int N = 256;
  int howmany = 21;
  fftw_complex* data = new fftw_complex[N*howmany];
  fftw_plan p;

  // OK
  p = fftw_plan_many_dft(1,&N,howmany,data,NULL,howmany,1,data,NULL,howmany,1,FFTW_FORWARD,FFTW_MEASURE);
  // do stuff  

  return 0;
}
4

1 回答 1

9

该功能按记录工作。我在步长上犯了一个错误,在这种情况下实际上应该是howmany这样。我已经更新了问题以反映这一点。

我发现 FFTW 的文档在没有示例的情况下有点难以理解(我可能只是文盲......),所以我在下面发布了一个更详细的示例,比较了fftw_plan_dft_1dwith的常用用法fftw_plan_many_dft。回顾一下,对于howmany长度N存储在引用为 的连续内存块中的数组,每个变换in的数组元素是jk

*(in + j*istride + k*idist)

以下两段代码是等价的。在第一个中,从某个 2D 数组的转换是显式完成的,在第二个中,fftw_plan_many_dft调用用于就地完成所有操作。

显式复制

int N, howmany;
// ...
fftw_complex* data = (fftw_complex*) fftw_malloc(N*howmany*sizeof(fftw_complex));
// ... load data with howmany arrays of length N 
int istride, idist;
// ... if data is column-major, set istride=howmany, idist=1
//    if data is row-major, set istride=1, idist=N

fftw_complex* in = (fftw_complex*) fftw_malloc(N*sizeof(fftw_complex));
fftw_complex* out = (fftw_complex*) fftw_malloc(N*sizeof(fftw_complex));
fftw_plan p = fftw_plan_dft_1d(N,in,out,FFTW_FORWARD,FFTW_MEASURE);
for (int k = 0; k < howmany; ++k) {
  for (int j = 0; j < N; ++j) {
    in[j] = data[j*istride + k*idist];
  }
  fftw_execute(p);
  // do something with out
}

计划许多

int N, howmany;
// ...
fftw_complex* data = (fftw_complex*) fftw_malloc(N*howmany*sizeof(fftw_complex));
// ... load data with howmany arrays of length N 
int istride, idist;
// ... if data is column-major, set istride=howmany, idist=1
//    if data is row-major, set istride=1, idist=N

fftw_plan p = fftw_plan_many_dft(1,&N,howmany,data,NULL,howmany,1,data,NULL,howmany,1,FFTW_FORWARD,FFTW_MEASURE);
fftw_execute(p);
于 2011-05-17T17:27:01.027 回答