1. #include <cufft.h>
  2. #include <iostream>
  3. #include <cuda_runtime.h>
  4. #include <helper_cuda.h>
  5. #include <stdio.h>
  6. using namespace std;
  7. #define CHANNEL_NUM  31 //通道数、FFT次数
  8. const int dataH = 32; //图像高度
  9. const int dataW = 8;  //图像宽度
  10. cufftHandle fftplanfwd;//创建句柄
  11. int main(void){
  12.  /* 开辟主机端的内存空间 */
  13.  printf("文件名planmany_cuda31.cu...\n");
  14.  printf("分配CPU内存空间...\n");
  15.  cufftComplex *h_Data = (cufftComplex*)malloc(dataH*CHANNEL_NUM*dataW* sizeof(cufftComplex));//可用cudaMallocHost设置
  16.  cufftComplex *h_resultFFT = (cufftComplex*)malloc(dataH*CHANNEL_NUM*dataW* sizeof(cufftComplex));
  17.  /* 开辟设备端的内存空间 */
  18.  printf("分配GPU内存空间...\n");
  19.  /* 定义设备端的内存空间 */
  20.  cufftComplex *d_Data;//device表示GPU内存,存储从cpu拷贝到GPU的数据
  21.  cufftComplex *fd_Data;//device表示GPU内存,R2C后存入cufftComplex类型数据
  22.  checkCudaErrors(cudaMalloc((void**)&d_Data, dataH*CHANNEL_NUM*dataW* sizeof(cufftComplex)));
  23.  checkCudaErrors(cudaMemset(d_Data, 0, dataH*CHANNEL_NUM * dataW* sizeof(cufftComplex))); // 初始为0
  24.  checkCudaErrors(cudaMalloc((void**)&fd_Data, dataH*CHANNEL_NUM*dataW* sizeof(cufftComplex))); // 开辟R2C后的设备内存
  25.  checkCudaErrors(cudaMemset(fd_Data, 0, dataH*CHANNEL_NUM*dataW* sizeof(cufftComplex))); // 初始为0
  26.  //随机初始化测试数据
  27.  printf("初始化测试数据...\n");
  28.  for (int i = 0; i < dataH*CHANNEL_NUM; i++){
  29.   for (int j = 0; j < dataW; j++){
  30.    h_Data[i*dataW + j].x = float(rand()%255);
  31.    h_Data[i*dataW + j].y = float(rand()%255);
  32.   }
  33.  }
  34.  //使用event计算时间
  35.  float time_elapsed = 0;
  36.  cudaEvent_t start, stop;
  37.  cudaEventCreate(&start);    //创建Event
  38.  cudaEventCreate(&stop);
  39.  const int rank = 2;//维数
  40.  int n[rank] = { 32, 8 };//n*m
  41.  int*inembed = n;//输入的数组size
  42.  int istride = 1;//数组内数据连续,为1
  43.  int idist = n[0] * n[1];//1个数组的内存大小
  44.  int*onembed = n;//输出是一个数组的size
  45.  int ostride = 1;//每点DFT后数据连续则为1
  46.  int odist = n[0] * n[1];//输出第一个数组与第二个数组的距离,即两个数组的首元素的距离
  47.  int batch = CHANNEL_NUM;//批量处理的批数
  48.  //采用cufftPlanMany方法
  49.  checkCudaErrors(
  50.   cufftPlanMany(&fftplanfwd, rank, n, inembed, istride, idist, onembed, ostride, odist, CUFFT_C2C, batch));//针对多信号同时进行FFT
  51.  //printf("拷贝CPU数据到GPU中...\n");
  52.  checkCudaErrors(
  53.   cudaMemcpy(d_Data, h_Data, dataW * dataH*CHANNEL_NUM * sizeof(cufftComplex), cudaMemcpyHostToDevice));
  54.  //printf("执行R2C-FFT...\n");
  55.  printf("开始计时...\n");
  56.  cudaEventRecord(start, 0);    //记录当前时间
  57.  checkCudaErrors(
  58.   cufftExecC2C(fftplanfwd, d_Data, fd_Data, CUFFT_FORWARD));
  59.  cudaEventRecord(stop, 0);    //记录当前时间
  60.  cudaEventSynchronize(start);    //Waits for an event to complete.
  61.  cudaEventSynchronize(stop);    //Waits for an event to complete.Record之前的任务
  62.  cudaEventElapsedTime(&time_elapsed, start, stop);    //计算时间差
  63.  //cudaDeviceSynchronize();
  64.  //printf("拷贝GPU数据返回到CPU中...\n");
  65.  checkCudaErrors(
  66.   cudaMemcpy(h_resultFFT, fd_Data, dataW *dataH*CHANNEL_NUM * sizeof(cufftComplex), cudaMemcpyDeviceToHost));//将fft后的数据拷贝回主机
  67.  //printf("显示返回到CPU中的数据...\n");
  68.  //for (int i = 0; i < dataH*CHANNEL_NUM*dataW; i++){
  69.  // cout << "h_resultFFT[" << i << "]=" << h_resultFFT[i].x << " + " << h_resultFFT[i].y << " i" << endl;
  70.  //}
  71.  cudaEventDestroy(start);    //destory the event
  72.  cudaEventDestroy(stop);
  73.  printf("执行时间:%f(ms)\n", time_elapsed);
  74.  /* 销毁句柄 */
  75.  checkCudaErrors(cufftDestroy(fftplanfwd));
  76.  /* 释放设备空间 */
  77.  checkCudaErrors(cudaFree(d_Data));
  78.  checkCudaErrors(cudaFree(fd_Data));
  79.  free(h_Data);
  80.  free(h_resultFFT);
  81.  return 0;
  82. }

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

CUDA cufftPlanMany的用法_31通道32*8像素的FFT的更多相关文章

  1. cuda中时间用法

    转载:http://blog.csdn.net/jdhanhua/article/details/4843653 在CUDA中统计运算时间,大致有三种方法: <1>使用cutil.h中的函 ...

  2. 并行计算提升32K*32K点(32位浮点数) FFT计算速度(4核八线程E3处理器)

    对32K*32K的随机数矩阵进行FFT变换,数的格式是32位浮点数.将产生的数据存放在堆上,对每一行数据进行N=32K的FFT,记录32K次fft的时间. 比较串行for循环和并行for循环的运行时间 ...

  3. 两通道实信号使用一个FFT同时计算算法

    前言 在工程的实际应用场景中,往往是需要最省资源量.而DSP资源和BRAM资源对FPGA来说弥足珍贵. 对于同时存在多个通道的实信号需要做FFT而言,常规做法是每个通道用一个FFT IP,FFT IP ...

  4. Java NIO 文件通道 FileChannel 用法

    FileChannel 提供了一种通过通道来访问文件的方式,它可以通过带参数 position(int) 方法定位到文件的任意位置开始进行操作,还能够将文件映射到直接内存,提高大文件的访问效率.本文将 ...

  5. CUDA 笔记

    名词解释 SM :Streaming Multiprocessor    而 Block 大致就是对应到 SM     所有的blocks 按照流水线被送到6个SM中进行计算 在 Compute Ca ...

  6. 【CUDA学习】GPU硬件结构

    GPU的硬件结构,也不是具体的硬件结构,就是与CUDA相关的几个概念:thread,block,grid,warp,sp,sm. sp: 最基本的处理单元,streaming processor  最 ...

  7. C++ IO 详细用法

    http://www.cnblogs.com/keam37/ keam所有 转载请注明出处 本文将分别从<iostream>,<sstream>,<fstream> ...

  8. CUDA学习ing..

    0.引言 本文记载了CUDA的学习过程~刚开始接触GPU相关的东西,包括图形.计算.并行处理模式等,先从概念性的东西入手,然后结合实践开始学习.CUDA感觉没有一种权威性的书籍,开发工具变动也比较快, ...

  9. CUDA零内存拷贝 疑问考证

    今天思考了一下CUDA零内存拷贝的问题,感觉在即将设计的程序中会派上用场,于是就查了一下相关信息. 以下是一些有帮助的链接: cuda中的零拷贝用法--针对二维指针 cuda中的零拷贝用法--针对一维 ...

随机推荐

  1. HDOJ2870 Largest Submatrix

    一道\(DP\) 原题链接 发现只有\(a,b,c\)三种情况,所以直接初始化成三个\(01\)方阵,找最大子矩阵即可. 我是先初始化垂直上的高度,然后对每一行处理出每个点向左向右的最大延伸,并不断计 ...

  2. 20172325 2018-2019-2 《Java程序设计》第四周学习总结

    20172325 2018-2019-2 <Java程序设计>第四周学习总结 教材学习内容总结 <Java软件结构与数据结构>第六章-列表 一.概述 1.列表是什么? 列表集合 ...

  3. 20172306《Java程序设计与数据结构》第八周学习总结

    20172306<Java程序设计>第8周学习总结 教材学习内容总结 第十章最开始自己看的时候,没怎么看懂,等老师讲完之后,又看了一遍,就理解了很多.第十章主要学习了以下几点: 1.对于几 ...

  4. 品味性能之道<十一>:JAVA中switch和if性能比较

    通常而言大家普遍的认知里switch case的效率高于if else.根据我的理解而言switch的查找类似于二叉树,if则是线性查找.按照此逻辑推理对于对比条件数目大于3时switch更优,并且对 ...

  5. Ubuntu 双网卡设置

    闲话不多说,直接正题 因为chinanet信号不强,所以买了个usb无线网卡,平常又要做开发,要连着开发板,不知怎么回事,一旦自带无线网卡连上内网的无线路由,就不能访问外网了. 网上搜了好久,终于查到 ...

  6. [Robot Framework] 怎么写动态等待?

    举例:Robot Framwork+WhiteLibrary,等待元素可用或不可用 Wait Until Object Is Enabled Wait Until Object Is Not Enab ...

  7. 论坛:获取当前原始请求中的远程IP地址

    topic.setIpAddr(ServletActionContext.getRequest().getRemoteAddr());//当前原始请求中的远程IP地址

  8. Linux修改/etc/profile配置错误command is not found自救方法

    export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin

  9. JDK8集合类源码解析 - HashMap

    java为数据结构中的映射定义了一个接口java.util.Map,此接口主要有四个常用的实现类,分别是HashMap.Hashtable.LinkedHashMap和TreeMap HashMap ...

  10. OneZero_Aphla发布总结以及自己的体会

    Aphla发布正式结束了.清明时节,总要祭奠点什么. 以下是这一周的燃尽图. 可以发现,并没有燃尽.所以OneZero的Aphla发布失败了. 失败原因有至少以下三点: 1.组长分配任务存在隐患,高风 ...