Cuda 卡夫特无法想出一个简单的例子

Cuda 卡夫特无法想出一个简单的例子,cuda,fft,cufft,Cuda,Fft,Cufft,我一整天都在努力,试图让一个基本的CUFFT示例正常工作。然而,我遇到了一个我无法识别的小问题。基本上我有一个x和y坐标的二维线性阵列vx。然后我只计算一个向前然后向后的袖口(原位),很简单。然后我复制回数组vx,通过NX*NY将其规格化,然后显示 #define NX 32 #define NY 32 #define LX (2*M_PI) #define LY (2*M_PI) float *x = new float[NX*NY]; float *y = new float[NX*NY];

我一整天都在努力,试图让一个基本的CUFFT示例正常工作。然而,我遇到了一个我无法识别的小问题。基本上我有一个x和y坐标的二维线性阵列vx。然后我只计算一个向前然后向后的袖口(原位),很简单。然后我复制回数组vx,通过NX*NY将其规格化,然后显示

#define NX 32
#define NY 32
#define LX (2*M_PI)
#define LY (2*M_PI)
float *x = new float[NX*NY];
float *y = new float[NX*NY];
float *vx = new float[NX*NY];
for(int j = 0; j < NY; j++){
    for(int i = 0; i < NX; i++){
        x[j*NX + i] = i * LX/NX;
        y[j*NX + i] = j * LY/NY;
        vx[j*NX + i] = cos(x[j*NX + i]);
    }
}
float *d_vx;
CUDA_CHECK(cudaMalloc(&d_vx, NX*NY*sizeof(float)));
CUDA_CHECK(cudaMemcpy(d_vx, vx, NX*NY*sizeof(float), cudaMemcpyHostToDevice));
cufftHandle planr2c;
cufftHandle planc2r;
CUFFT_CHECK(cufftPlan2d(&planr2c, NY, NX, CUFFT_R2C));
CUFFT_CHECK(cufftPlan2d(&planc2r, NY, NX, CUFFT_C2R));
CUFFT_CHECK(cufftSetCompatibilityMode(planr2c, CUFFT_COMPATIBILITY_NATIVE));
CUFFT_CHECK(cufftSetCompatibilityMode(planc2r, CUFFT_COMPATIBILITY_NATIVE));
CUFFT_CHECK(cufftExecR2C(planr2c, (cufftReal *)d_vx, (cufftComplex *)d_vx));
CUFFT_CHECK(cufftExecC2R(planc2r, (cufftComplex *)d_vx, (cufftReal *)d_vx));
CUDA_CHECK(cudaMemcpy(vx, d_vx, NX*NY*sizeof(cufftReal), cudaMemcpyDeviceToHost));
for (int j = 0; j < NY; j++){
    for (int i = 0; i < NX; i++){
        printf("%.3f ", vx[j*NX + i]/(NX*NY));
    }
    printf("\n");
}
#定义NX 32
#定义NY 32
#定义LX(2*M_PI)
#定义LY(2*M_PI)
浮动*x=新浮动[NX*NY];
浮动*y=新浮动[NX*NY];
浮动*vx=新浮动[NX*NY];
对于(int j=0;j

当vx被定义为cos(x)或sin(x)时,它工作得很好,但当使用sin(y)或cos(y)时,它会返回正确的函数(sin或cos),但振幅为一半(即,在0.5和-0.5之间振荡,而不是1和-1)!请注意,使用sin(2*y)或cos(2*y)(或sin(4*y),cos(4*y),…)可以很好地工作。有什么想法吗?

这里的问题是,就地实-复变换的输入和输出是一种复杂类型,其大小与输入的实数据不同(它是两倍大)。您没有分配足够的内存来保存实到复转换的中间复杂结果。引用文件:

cufftExecR2C()(cufftExecD2Z())执行单个精度 (双精度)从实到复,隐式向前,袖口 改造计划。CUFFT将GPU内存用作 idata参数。此函数用于存储非冗余傅里叶变换 odata数组中的系数。指向idata和odata的指针都是 需要以单精度与Cufft复杂数据类型对齐 双精度转换和压缩双重复杂数据类型 转变

解决方案是分配第二个设备缓冲区来保存中间结果,或者扩大就地分配,使其足够大以保存复杂数据。因此,核心转换代码更改为:

float *d_vx;
CUDA_CHECK(cudaMalloc(&d_vx, NX*NY*sizeof(cufftComplex)));
CUDA_CHECK(cudaMemcpy(d_vx, vx, NX*NY*sizeof(cufftComplex), cudaMemcpyHostToDevice));
cufftHandle planr2c;
cufftHandle planc2r;
CUFFT_CHECK(cufftPlan2d(&planr2c, NY, NX, CUFFT_R2C));
CUFFT_CHECK(cufftPlan2d(&planc2r, NY, NX, CUFFT_C2R));
CUFFT_CHECK(cufftSetCompatibilityMode(planr2c, CUFFT_COMPATIBILITY_NATIVE));
CUFFT_CHECK(cufftSetCompatibilityMode(planc2r, CUFFT_COMPATIBILITY_NATIVE));
CUFFT_CHECK(cufftExecR2C(planr2c, (cufftReal *)d_vx, d_vx));
CUFFT_CHECK(cufftExecC2R(planc2r, d_vx, (cufftReal *)d_vx));
CUDA_CHECK(cudaMemcpy(vx, d_vx, NX*NY*sizeof(cufftComplex), cudaMemcpyDeviceToHost));
[免责声明:在浏览器中编写,从未编译或测试,使用风险自负]

注意:您需要调整主机代码以匹配输入和数据的大小和类型


作为最后的评论,如果要添加额外的8行或10行代码,将您发布的内容转换为可编译的,有人试图帮助您处理的可运行示例?

这里的问题是,就地实-复转换的输入和输出是一种复杂类型,其大小与输入的实数据不同(它是两倍大)。您没有分配足够的内存来保存实到复转换的中间复杂结果。引用文件:

cufftExecR2C()(cufftExecD2Z())执行单个精度 (双精度)从实到复,隐式向前,袖口 改造计划。CUFFT将GPU内存用作 idata参数。此函数用于存储非冗余傅里叶变换 odata数组中的系数。指向idata和odata的指针都是 需要以单精度与Cufft复杂数据类型对齐 双精度转换和压缩双重复杂数据类型 转变

解决方案是分配第二个设备缓冲区来保存中间结果,或者扩大就地分配,使其足够大以保存复杂数据。因此,核心转换代码更改为:

float *d_vx;
CUDA_CHECK(cudaMalloc(&d_vx, NX*NY*sizeof(cufftComplex)));
CUDA_CHECK(cudaMemcpy(d_vx, vx, NX*NY*sizeof(cufftComplex), cudaMemcpyHostToDevice));
cufftHandle planr2c;
cufftHandle planc2r;
CUFFT_CHECK(cufftPlan2d(&planr2c, NY, NX, CUFFT_R2C));
CUFFT_CHECK(cufftPlan2d(&planc2r, NY, NX, CUFFT_C2R));
CUFFT_CHECK(cufftSetCompatibilityMode(planr2c, CUFFT_COMPATIBILITY_NATIVE));
CUFFT_CHECK(cufftSetCompatibilityMode(planc2r, CUFFT_COMPATIBILITY_NATIVE));
CUFFT_CHECK(cufftExecR2C(planr2c, (cufftReal *)d_vx, d_vx));
CUFFT_CHECK(cufftExecC2R(planc2r, d_vx, (cufftReal *)d_vx));
CUDA_CHECK(cudaMemcpy(vx, d_vx, NX*NY*sizeof(cufftComplex), cudaMemcpyDeviceToHost));
[免责声明:在浏览器中编写,从未编译或测试,使用风险自负]

注意:您需要调整主机代码以匹配输入和数据的大小和类型


最后一点意见是,如果要添加额外的8行或10行代码,将您发布的内容转换为可编译、可运行的示例,以便有人帮助您使用,会有那么困难吗?

为什么您的第一个cudaMemcpy操作指定了cudaMemcpyDeviceToHost?这毫无意义,也与指针的顺序不匹配。如果您的CUDA_CHECK宏没有在那里抛出错误,则说明您的宏有问题。很抱歉,我没有复制/粘贴正确的行,在我的代码中,复制的意思是正确的。我更新了您以前的代码行,但在任何地方都不可能是正确的。如果该行代码出现在代码的其他地方,则它是错误的。顺便说一句,SO希望您为类似的问题提供一个SSCCE.org代码。我刚刚以双精度重新计算了它,它可以工作。但我无法解释原因,可能是内存布局有问题。为什么您的第一个cudaMemcpy操作指定cudaMemcpyDeviceToHost?这毫无意义,也与指针的顺序不匹配。如果您的CUDA_CHECK宏没有在那里抛出错误,则说明您的宏有问题。很抱歉,我没有复制/粘贴正确的行,在我的代码中,复制的意思是正确的。我更新了您以前的代码行,但在任何地方都不可能是正确的。如果该行代码出现在代码的其他地方,则它是错误的。顺便说一句,所以我希望你