首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CuFFT双到复

CuFFT双到复
EN

Stack Overflow用户
提问于 2014-07-17 16:45:09
回答 1查看 1.1K关注 0票数 0

我想用CuFFT Lib做一个从double到std::complex的快速傅立叶变换。我的密码就像

代码语言:javascript
复制
#include <complex>
#include <iostream>
#include <cufft.h>
#include <cuda_runtime_api.h>

typedef std::complex<double> Complex;
using namespace std;

int main(){
  int n = 100;
  double* in;
  Complex* out;
  in = (double*) malloc(sizeof(double) * n);
  out = (Complex*) malloc(sizeof(Complex) * n/2+1);
  for(int i=0; i<n; i++){
     in[i] = 1;
  }

  cufftHandle plan;
  plan = cufftPlan1d(&plan, n, CUFFT_D2Z, 1);
  unsigned int mem_size = sizeof(double)*n;
  cufftDoubleReal *d_in;
  cufftDoubleComplex *d_out;
  cudaMalloc((void **)&d_in, mem_size);
  cudaMalloc((void **)&d_out, mem_size);
  cudaMemcpy(d_in, in, mem_size, cudaMemcpyHostToDevice);
  cudaMemcpy(d_out, out, mem_size, cudaMemcpyHostToDevice);
  int succes = cufftExecD2Z(plan,(cufftDoubleReal *) d_in,(cufftDoubleComplex *) d_out);
  cout << succes << endl;
  cudaMemcpy(out, d_out, mem_size, cudaMemcpyDeviceToHost);

  for(int i=0; i<n/2; i++){
     cout << "out: " << i << " "  << out[i].real() << " " <<  out[i].imag() << endl;
  }
  return 0;
}

但在我看来,这肯定是错的,因为我认为转换后的值应该是10 0 0 0.或者没有归一化100 0 0 0.但我只得到了0 0 0.

此外,我更希望cufftExecD2Z能够正常工作,这应该是可能的,但我还没有弄清楚如何正确地做到这一点。有人能帮忙吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-07-17 17:11:08

您的代码有各种各样的错误。您可能应该检查袖口文件和示例代码。

  1. 您应该对所有API返回值执行正确的cuda错误检查和正确的cufft错误检查。
  2. cufftPlan1d函数的返回值不进入计划: plan = cufftPlan1d(&plan,n,CUFFT_D2Z,1); 函数本身设置计划(这就是将&plan传递给函数的原因),然后当将返回值分配给计划时,它会破坏由函数设置的计划。
  3. 您正确地识别了输出的大小可以是((N/2)+1),但是在主机端没有为它分配适当的空间: out =(复数*)malloc(大号(复数)* n/2+1); 或者在设备方面: 无符号int mem_size = sizeof(double)*n;cudaMalloc((void **)&d_out,mem_size);

下面的代码修复了上面的一些问题,足以得到您想要的结果(100,0,0,.)

代码语言:javascript
复制
#include <complex>
#include <iostream>
#include <cufft.h>
#include <cuda_runtime_api.h>

#define cudaCheckErrors(msg) \
    do { \
        cudaError_t __err = cudaGetLastError(); \
        if (__err != cudaSuccess) { \
            fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \
                msg, cudaGetErrorString(__err), \
                __FILE__, __LINE__); \
            fprintf(stderr, "*** FAILED - ABORTING\n"); \
            exit(1); \
        } \
    } while (0)


typedef std::complex<double> Complex;
using namespace std;

int main(){
  int n = 100;
  double* in;
  Complex* out;
#ifdef IN_PLACE
  in = (double*) malloc(sizeof(Complex) * (n/2+1));
  out = (Complex*)in;
#else
  in = (double*) malloc(sizeof(double) * n);
  out = (Complex*) malloc(sizeof(Complex) * (n/2+1));
#endif
  for(int i=0; i<n; i++){
     in[i] = 1;
  }

  cufftHandle plan;
  cufftResult res = cufftPlan1d(&plan, n, CUFFT_D2Z, 1);
  if (res != CUFFT_SUCCESS)  {cout << "cufft plan error: " << res << endl; return 1;}
  cufftDoubleReal *d_in;
  cufftDoubleComplex *d_out;
  unsigned int out_mem_size = (n/2 + 1)*sizeof(cufftDoubleComplex);
#ifdef IN_PLACE
  unsigned int in_mem_size = out_mem_size;
  cudaMalloc((void **)&d_in, in_mem_size);
  d_out = (cufftDoubleComplex *)d_in;
#else
  unsigned int in_mem_size = sizeof(cufftDoubleReal)*n;
  cudaMalloc((void **)&d_in, in_mem_size);
  cudaMalloc((void **)&d_out, out_mem_size);
#endif
  cudaCheckErrors("cuda malloc fail");
  cudaMemcpy(d_in, in, in_mem_size, cudaMemcpyHostToDevice);
  cudaCheckErrors("cuda memcpy H2D fail");
  res = cufftExecD2Z(plan,d_in, d_out);
  if (res != CUFFT_SUCCESS)  {cout << "cufft exec error: " << res << endl; return 1;}
  cudaMemcpy(out, d_out, out_mem_size, cudaMemcpyDeviceToHost);
  cudaCheckErrors("cuda memcpy D2H fail");

  for(int i=0; i<n/2; i++){
     cout << "out: " << i << " "  << out[i].real() << " " <<  out[i].imag() << endl;
  }
  return 0;
}

回顾文献资料关于在真实到复杂情况下进行就地转换所必需的内容。上面的代码可以用-DIN_PLACE重新编译,以查看就地转换的行为,以及所需的代码更改。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24809179

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档