zoukankan      html  css  js  c++  java
  • CUDA cufftPlanMany的用法_31通道32*8像素的FFT

    #include <cufft.h>
    #include <iostream>
    #include <cuda_runtime.h>
    #include <helper_cuda.h>
    #include <stdio.h>
    using namespace std; #define CHANNEL_NUM  31 //通道数、FFT次数 const int dataH = 32; //图像高度 const int dataW = 8;  //图像宽度 cufftHandle fftplanfwd;//创建句柄 int main(void){  /* 开辟主机端的内存空间 */  printf("文件名planmany_cuda31.cu... ");  printf("分配CPU内存空间... ");  cufftComplex *h_Data = (cufftComplex*)malloc(dataH*CHANNEL_NUM*dataW* sizeof(cufftComplex));//可用cudaMallocHost设置  cufftComplex *h_resultFFT = (cufftComplex*)malloc(dataH*CHANNEL_NUM*dataW* sizeof(cufftComplex));  /* 开辟设备端的内存空间 */  printf("分配GPU内存空间... ");  /* 定义设备端的内存空间 */  cufftComplex *d_Data;//device表示GPU内存,存储从cpu拷贝到GPU的数据  cufftComplex *fd_Data;//device表示GPU内存,R2C后存入cufftComplex类型数据  checkCudaErrors(cudaMalloc((void**)&d_Data, dataH*CHANNEL_NUM*dataW* sizeof(cufftComplex)));  checkCudaErrors(cudaMemset(d_Data, 0, dataH*CHANNEL_NUM * dataW* sizeof(cufftComplex))); // 初始为0  checkCudaErrors(cudaMalloc((void**)&fd_Data, dataH*CHANNEL_NUM*dataW* sizeof(cufftComplex))); // 开辟R2C后的设备内存  checkCudaErrors(cudaMemset(fd_Data, 0, dataH*CHANNEL_NUM*dataW* sizeof(cufftComplex))); // 初始为0  //随机初始化测试数据  printf("初始化测试数据... ");  for (int i = 0; i < dataH*CHANNEL_NUM; i++){   for (int j = 0; j < dataW; j++){    h_Data[i*dataW + j].x = float(rand()%255);    h_Data[i*dataW + j].y = float(rand()%255);   }  }  //使用event计算时间  float time_elapsed = 0;  cudaEvent_t start, stop;  cudaEventCreate(&start);    //创建Event  cudaEventCreate(&stop);  const int rank = 2;//维数  int n[rank] = { 32, 8 };//n*m  int*inembed = n;//输入的数组size  int istride = 1;//数组内数据连续,为1  int idist = n[0] * n[1];//1个数组的内存大小  int*onembed = n;//输出是一个数组的size  int ostride = 1;//每点DFT后数据连续则为1  int odist = n[0] * n[1];//输出第一个数组与第二个数组的距离,即两个数组的首元素的距离  int batch = CHANNEL_NUM;//批量处理的批数  //采用cufftPlanMany方法  checkCudaErrors(   cufftPlanMany(&fftplanfwd, rank, n, inembed, istride, idist, onembed, ostride, odist, CUFFT_C2C, batch));//针对多信号同时进行FFT  //printf("拷贝CPU数据到GPU中... ");  checkCudaErrors(   cudaMemcpy(d_Data, h_Data, dataW * dataH*CHANNEL_NUM * sizeof(cufftComplex), cudaMemcpyHostToDevice));  //printf("执行R2C-FFT... ");  printf("开始计时... ");  cudaEventRecord(start, 0);    //记录当前时间  checkCudaErrors(   cufftExecC2C(fftplanfwd, d_Data, fd_Data, CUFFT_FORWARD));  cudaEventRecord(stop, 0);    //记录当前时间  cudaEventSynchronize(start);    //Waits for an event to complete.  cudaEventSynchronize(stop);    //Waits for an event to complete.Record之前的任务  cudaEventElapsedTime(&time_elapsed, start, stop);    //计算时间差  //cudaDeviceSynchronize();  //printf("拷贝GPU数据返回到CPU中... ");  checkCudaErrors(   cudaMemcpy(h_resultFFT, fd_Data, dataW *dataH*CHANNEL_NUM * sizeof(cufftComplex), cudaMemcpyDeviceToHost));//将fft后的数据拷贝回主机  //printf("显示返回到CPU中的数据... ");  //for (int i = 0; i < dataH*CHANNEL_NUM*dataW; i++){  // cout << "h_resultFFT[" << i << "]=" << h_resultFFT[i].x << " + " << h_resultFFT[i].y << " i" << endl;  //}  cudaEventDestroy(start);    //destory the event  cudaEventDestroy(stop);  printf("执行时间:%f(ms) ", time_elapsed);  /* 销毁句柄 */  checkCudaErrors(cufftDestroy(fftplanfwd));  /* 释放设备空间 */  checkCudaErrors(cudaFree(d_Data));  checkCudaErrors(cudaFree(fd_Data));  free(h_Data);  free(h_resultFFT);  return 0; }

     CUDA8.0版本+VS2013的编译环境

    再谈FFT:

    1、库利-图基提出的基于蝶形算法的FFT,当变换的序列数量是2^n个那么变换速度很快;所以再用FFT是经常需要判断需要变换点的数量,不是2^n个则需要补0凑齐。

    2、做FFt分析时,幅值的大小与FFT选择的点数相关,但不影响分析的结果,在IFFT时已经做了处理,要得到真实的振幅大小,只要将得到的变换结果乘以2除以N即可。

    3、一维FFT与二维FFT原理不一样,二维如果用一维fft函数变换,可以分按行向量傅里叶变换、或按列向量傅里叶变换,二维数组整体对应的傅里叶变换函数维fft2();cufft中对应cufftplan2D();多维对应cufftplanmany();

    4、cufftplanmany()数据的接口是一个数组首地址。用法详解:比如你有n通道的j*k维二维数组,那么可以将n个j*k数组的数组存到一个(j*n)*k的二维数组中,然后给赋予函数这个二维数组的首地址,然后设置好原来是j*k维的二维数组,一共有n个这样的数组,且它们是连续存在的(可以看上面代码来理解)。

    5、傅里叶变换的作用在于将时域的信号转化到频域来处理,对于两个时域上函数的卷积运算可以转化到频域的乘积上来处理.

  • 相关阅读:
    Windows编程--线程的睡眠方式
    Windows编程-- 等待函数
    Windows编程--线程的切换
    Windows编程-- 用户方式中线程的同步关键代码段(临界区)
    Windows编程--挂起和恢复线程的运行
    Windows编程-- 用户方式中线程的同步原子访问:互锁的函数家族
    Windows编程--线程之GetExitCodeThread()
    Windows编程-- 对Critical Section的封装
    Windows编程--线程的身份标识
    如何在oracle中限制返回结果集的大小
  • 原文地址:https://www.cnblogs.com/liang2713020/p/6627429.html
Copyright © 2011-2022 走看看