【问题标题】:How to use fftw Guru interface如何使用 fftw Guru 界面
【发布时间】:2016-10-08 23:23:38
【问题描述】:

我曾经使用fftw_plan_dft 进行多维傅里叶变换。

fftw_plan fftw_plan_dft(int rank, const int *n, fftw_complex *in,
                        fftw_complex *out, int sign, unsigned flags);

现在我想把64位整数传给fftw,看来我需要使用fftw guru接口。

 fftw_plan fftw_plan_guru64_dft(
     int rank, const fftw_iodim64 *dims,
     int howmany_rank, const fftw_iodim64 *howmany_dims,
     fftw_complex *in, fftw_complex *out,
     int sign, unsigned flags);

但我不明白howmany_rankhowmany_dims 是什么意思。 fftw_plan_guru_dft 的手册说:

这两个函数分别为交错格式和拆分格式规划了一个复杂数据、多维 DFT。变换维度由(rank, dims)在维度(howmany_rank, howmany_dims)的多维向量(循环)上给出。 dims 和 howmany_dims 应该分别指向长度为 rank 和 howmany_rank 的 fftw_iodim 数组。

我知道什么是“维度的多维向量(循环)(howmany_rank、h​​owmany_dims)”是什么意思。能否举个例子或解释一下如何使用这个大师界面?

【问题讨论】:

  • 既然您在此标记了 pyfftw,Here's an example。该行正在调用指向 guru 接口函数的函数指针。阅读上面的 python 以了解如何填充参数。
  • 谢谢@Henry Gomersall。我可以看到这条线正在使用大师界面。我正在努力阅读这个 python 代码。不过有点长,你给我解释一下howmany_rankhowmany_dims的意思可以吗?
  • 我建议阅读文档并认真思考。我看不出有什么捷径。你会发现你需要各种信息来指定任意变换,到那时它就会变得很明显。或者,您可以花一些精力来理解我链接的代码,这将使一切变得清晰(这是一个很好的例子,因为它描述了从形状、步幅和变换轴到 FFTW 参数的一般映射)。
  • @Henry Gomersall 谢谢。

标签: c++ fft fftw pyfftw


【解决方案1】:

如果多维数组的大小和步幅大于 2^32,64 bit guru interface 就很有用了。

创建复杂到复杂 DTF 的函数原型是:

fftw_plan fftw_plan_guru64_dft(
 int rank, const fftw_iodim64 *dims,
 int howmany_rank, const fftw_iodim64 *howmany_dims,
 fftw_complex *in, fftw_complex *out,
 int sign, unsigned flags);

地点:

  • rank 是要执行的 FFTW 变换的秩,即维数。
  • dims 是一个大小为 rank 的数组。对于每个维度idims[i].n 是行的大小,dims[i].is 是输入数组的行间距,dims[i].os 是输出数组的行间距。例如,如果数组在内存中是连续的,那么the documentation of the guru interface 建议使用递归dims[i].is = n[i+1] * dims[i+1].is。 要执行的转换次数和起点之间的偏移量由howmany_rankhowmany_dims 给出。
  • howmany_rank 指定具有特定偏移的变换的数量。
  • howmany_dims 是一个大小为 howmany_rank 的数组。对于每个变换ihowmany_dims[i].n 是要计算的变换的数量,每个变换都具有输入之间的偏移量howmany_dims[i].is 和输出之间的偏移量howmany_dims[i].os

Confusion about FFTW3 guru interface: 3 simultaneous complex FFTs 中提供了有关这些参数的更多详细信息

以下代码调用fftw_plan_guru64_dft(),因此它执行与fftw_plan_dft_3d() 相同的操作。可以通过gcc main.c -o main -lfftw3 -lm -Wall编译:

#include<stdlib.h>
#include<complex.h>
#include<math.h>
#include<fftw3.h>

int main(void){

    fftw_plan p;
    unsigned long int N = 10;
    unsigned long int M = 12;
    unsigned long int P = 14;
    fftw_complex *in=fftw_malloc(N*M*P*sizeof(fftw_complex));
    if(in==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
    fftw_complex *out=fftw_malloc(N*M*P*sizeof(fftw_complex));
    if(out==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
    unsigned int i,j,k;

    int rank=3;
    fftw_iodim64 *dims=malloc(rank*sizeof(fftw_iodim64));
    if(dims==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
    dims[0].n=N;
    dims[0].is=P*M;
    dims[0].os=P*M;
    dims[1].n=M;
    dims[1].is=P;
    dims[1].os=P;
    dims[2].n=P;
    dims[2].is=1;
    dims[2].os=1;

    int howmany_rank=1;
    fftw_iodim64 *howmany_dims=malloc(howmany_rank*sizeof(fftw_iodim64));
    if(howmany_dims==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
    howmany_dims[0].n=1;
    howmany_dims[0].is=1;
    howmany_dims[0].os=1;

    printf("sizeof fftw complex %ld\n",sizeof(fftw_complex));
    printf("sizeof fftw_iodim64 %ld\n",sizeof(fftw_iodim64));
    printf("creating the plan\n");
    p=fftw_plan_guru64_dft(rank, dims,howmany_rank, howmany_dims,in, out,FFTW_FORWARD, FFTW_ESTIMATE);
    if (p==NULL){fprintf(stderr,"plan creation failed\n");exit(1);}
    printf("created the plan\n");

    for(i=0;i<N;i++){
        for(j=0;j<M;j++){
            for(k=0;k<P;k++){
                //printf("ijk\n");
                in[(i*M+j)*P+k]=30.+12.*sin(2*3.1415926535*i/((double)N))*sin(2*3.1415926535*j/((double)M))*sin(2*3.1415926535*k/((double)P))*I;
            }
        }
    }

    fftw_execute(p);

    for (i = 0; i < N; i++){
        for (j = 0; j < M; j++){
            for (k = 0; k < P; k++){
                printf("result: %d %d %d %g %gI\n", i,j,k, creal(out[(i*M+j)*P+k]), cimag(out[(i*M+j)*P+k]));
            }
        }
    }


    fftw_destroy_plan(p);
    fftw_free(in);
    fftw_free(out);

    free(dims);
    free(howmany_dims);

    return(0);
}

例如,guru 界面可用于计算复杂 3D 电场的 DFT。在网格的每个点,电场都是大小为 3 的向量。因此,我可以将电场存储为 4D 数组,最后一个维度指定向量的分量。最后,guru 界面可用于一次执行三个 3D DFT:

#include<stdlib.h>
#include<complex.h>
#include<math.h>
#include<fftw3.h>

int main(void){

    fftw_plan p;
    unsigned long int N = 10;
    unsigned long int M = 12;
    unsigned long int P = 14;
    unsigned long int DOF = 3;
    fftw_complex *in=fftw_malloc(N*M*P*DOF*sizeof(fftw_complex));
    if(in==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
    fftw_complex *out=fftw_malloc(N*M*P*DOF*sizeof(fftw_complex));
    if(out==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
    unsigned int i,j,k;

    int rank=3;
    fftw_iodim64 *dims=malloc(rank*sizeof(fftw_iodim64));
    if(dims==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
    dims[0].n=N;
    dims[0].is=P*M*DOF;
    dims[0].os=P*M*DOF;
    dims[1].n=M;
    dims[1].is=P*DOF;
    dims[1].os=P*DOF;
    dims[2].n=P;
    dims[2].is=DOF;
    dims[2].os=DOF;

    int howmany_rank=1;
    fftw_iodim64 *howmany_dims=malloc(howmany_rank*sizeof(fftw_iodim64));
    if(howmany_dims==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
    howmany_dims[0].n=DOF;
    howmany_dims[0].is=1;
    howmany_dims[0].os=1;

    printf("sizeof fftw complex %ld\n",sizeof(fftw_complex));
    printf("sizeof fftw_iodim64 %ld\n",sizeof(fftw_iodim64));
    printf("creating the plan\n");
    p=fftw_plan_guru64_dft(rank, dims,howmany_rank, howmany_dims,in, out,FFTW_FORWARD, FFTW_ESTIMATE);
    if (p==NULL){fprintf(stderr,"plan creation failed\n");exit(1);}
    printf("created the plan\n");

    for(i=0;i<N;i++){
        for(j=0;j<M;j++){
            for(k=0;k<P;k++){
                //printf("ijk\n");
                in[((i*M+j)*P+k)*DOF]=30.+12.*sin(2*3.1415926535*i/((double)N))*sin(2*3.1415926535*j/((double)M))*sin(2*3.1415926535*k/((double)P))*I;
                in[((i*M+j)*P+k)*DOF+1]=42.0;
                in[((i*M+j)*P+k)*DOF+2]=1.0;
            }
        }
    }

    fftw_execute(p);

    for (i = 0; i < N; i++){
        for (j = 0; j < M; j++){
            for (k = 0; k < P; k++){
                printf("result: %d %d %d || %g %gI | %g %gI | %g %gI\n", i,j,k, creal(out[((i*M+j)*P+k)*DOF]), cimag(out[((i*M+j)*P+k)*DOF]),creal(out[((i*M+j)*P+k)*DOF+1]), cimag(out[((i*M+j)*P+k)*DOF+1]),creal(out[((i*M+j)*P+k)*DOF+2]), cimag(out[((i*M+j)*P+k)*DOF+2]));
            }
        }
    }


    fftw_destroy_plan(p);
    fftw_free(in);
    fftw_free(out);

    free(dims);
    free(howmany_dims);

    return(0);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-26
    • 1970-01-01
    • 2015-10-11
    • 2017-10-31
    • 1970-01-01
    • 1970-01-01
    • 2013-08-13
    相关资源
    最近更新 更多