CUDA 中 FFT 的使用

@(10.CUDA)[CUDA,并行,fft]

1. 流程

  1. 使用cufftHandle创建句柄
  2. 使用cufftPlan1d(),cufftPlan3d(),cufftPlan3d(),cufftPlanMany()对句柄进行配置,主要是配置句柄对应的信号长度,信号类型,在内存中的存储形式等信息。
    • cufftPlan1d():针对单个 1 维信号
    • cufftPlan2d():针对单个 2 维信号
    • cufftPlan3d():针对单个 3 维信号
    • cufftPlanMany():针对多个信号同时进行 fft
  3. 使用cufftExec()函数执行 fft
  4. 使用cufftDestroy()函数释放 GPU 资源

2. 单个 1 维信号的 fft

假设要执行 fft 的信号data_dev的长度为N,并且已经传输到 GPU 显存中,data_dev数据的类型为cufftComplex,可以用一下方式产生主机段的data_dev,如下所示:

Alt text

    cufftComplex *data_Host = (cufftComplex*)malloc(NX*BATCH*sizeof(cufftComplex)); // 主机端数据头指针// 初始数据for (int i = 0; i < NX; i++){data_Host[i].x = float((rand() * rand()) % NX) / NX;data_Host[i].y = float((rand() * rand()) % NX) / NX;}

然后用cudaMemcpy()将主机端的data_host拷贝到设备端的data_dev,即可用下述方法执行 fft :

    cufftHandle plan; // 创建cuFFT句柄cufftPlan1d(&plan, N, CUFFT_C2C, BATCH);cufftExecC2C(plan, data_dev, data_dev, CUFFT_FORWARD); // 执行 cuFFT,正变换

cufftPlan1d()

  • 第一个参数就是要配置的 cuFFT 句柄;
  • 第二个参数为要进行 fft 的信号的长度;
  • 第三个CUFFT_C2C为要执行 fft 的信号输入类型及输出类型都为复数;CUFFT_C2R表示输入复数,输出实数;CUFFT_R2C表示输入实数,输出复数;CUFFT_R2R表示输入实数,输出实数;
  • 第四个参数BATCH表示要执行 fft 的信号的个数,新版的已经使用cufftPlanMany()来同时完成多个信号的 fft。

cufftExecC2C()

  • 第一个参数就是配置好的 cuFFT 句柄;
  • 第二个参数为输入信号的首地址;
  • 第三个参数为输出信号的首地址;
  • 第四个参数CUFFT_FORWARD表示执行的是 fft 正变换;CUFFT_INVERSE表示执行 fft 逆变换。

需要注意的是,执行完逆 fft 之后,要对信号中的每个值乘以 $\frac{1}{N}$

完整代码:GitHub

3. 多个 1 维信号的 fft

要进行多个信号的 fft,就不得不使用 cufftPlanMany 函数,该函数的参数比较多,需要特别介绍,

cufftPlanMany(cufftHandle *plan, int rank, int *n, int *inembed, int istride, int idist, int *onembed, int ostride, int odist, cufftType type, int batch);

为了叙述的更准确,此处先引入一个图,表示输入数据在内存中的布局,如下图所示,数据在内存中按行优先存储,但是现有的信号为一列表示一个信号,后四列灰白色的表示无关数据,要对前 12 个彩色的列信号分别进行 fft。

Alt text

  • plan:表示 cufft 句柄
  • rank:表示进行 fft 的每个信号的维度数,一维信号为 1,二维信号为2,三维信号为 3 ,针对上图,rank = 1
  • n:表示进行 fft 的每个信号的行数,列数,页数,必须用数组形式表示,例如假设要进行 fft 的每个信号的行、列、页为(m, n, k),则 int n[rank] = {m, n, k};针对上图,int n[1] = {5}
  • inembed:表示输入数据的[页数,列数,行数],这是三维信号的情况;二维信号则为[列数,行数];一维信号为[行数];inembed[0] 这个参数会被忽略,也就是此处 inembed 可以为{0},{1},{2}等等。
  • istride:表示每个输入信号相邻两个元素的距离,在此处 istride = 16(每个信号相邻两个元素间的距离为16)
  • idist:表示两个连续输入信号的起始元素之间的间隔,在此处为 idist = 1(第一个信号的第一个元素与第二个信号的第一个元素的间隔为1);如果把上图数据的每一行看成一个信号,那么应该为 idist = 16;
  • onembed:表示输出数据的[页数,列数,行数],这是三维信号的情况;二维信号则为[列数,行数];一维信号为[行数];onembed[0] 这个参数会被忽略,也就是此处 onembed 可以为{0},{1},{2}等等。
  • ostride:表示每个输出信号相邻两个元素的距离,在此处 ostride = 16(每个信号相邻两个元素间的距离为16)
  • odist:表示两个连续信号的起始元素之间的间隔,在此处为 odist = 1(第一个信号的第一个元素与第二个信号的第一个元素的间隔为1);如果把上图数据的每一行看成一个信号,那么应该为 odist = 16;

如下所示:是第 b 个信号的 [z][y][x] (表示第 z 列,第 y 行,第 x 页的元素)的索引(由于 c 和 c++ 中数组的声明方式的问题,array[X][Y][Z]表示数组有 X 页,Y 行,Z 列) :

‣ 1D

input[ b * idist + x * istride ]output[ b * odist + x * ostride ]

‣ 2D

input[ b * idist + (x * inembed[1] + y) * istride ]output[ b * odist + (x * onembed[1] + y) * ostride ]

‣ 3D

input[b * idist + (x * inembed[1] * inembed[2] + y * inembed[2] + z) * istride]output[b * odist + (x * onembed[1] * onembed[2] + y * onembed[2] + z) * ostride]

    /* 申请 cufft 句柄*/cufftHandle plan_Nfft_Many; // 创建cuFFT句柄const int rank = 1; // 一维 fftint n[rank] = { Nfft }; // 进行 fft 的信号的长度为 Nfftint inembed[1] = { 0 }; // 输入数据的[页数,列数,行数](3维);[列数,行数](2维)int onembed[1] = { 0 }; // 输出数据的[页数,列数,行数];[列数,行数](2维)int istride = NXWITH0; // 每个输入信号相邻两个元素的距离int idist = 1; // 每两个输入信号第一个元素的距离int ostride = NXWITH0; // 每个输出信号相邻两个元素的距离int odist = 1; // 每两个输出信号第一个元素的距离int batch = NX; // 进行 fft 的信号个数cufftPlanMany(&plan_Nfft_Many, rank, n, inembed, istride, idist, onembed, ostride, odist, CUFFT_C2C, batch);/* 核心部份 */cudaMemcpy(data_dev, data_Host, Nfft * NXWITH0 * sizeof(cufftComplex), cudaMemcpyHostToDevice);cufftExecC2C(plan_Nfft_Many, data_dev, data_dev, CUFFT_FORWARD); // 执行 cuFFT,正变换cufftExecC2C(plan_Nfft_Many, data_dev, data_dev, CUFFT_INVERSE); // 执行 cuFFT,逆变换CufftComplexScale<<<dimGrid2D_NXWITH0_Nfft, dimBlock2D>>>(data_dev, data_dev, 1.0f / Nfft); // 乘以系数cudaMemcpy(resultIFFT, data_dev, Nfft * NXWITH0 * sizeof(cufftComplex), cudaMemcpyDeviceToHost);

完整代码:GitHub

CUDA 中 FFT 的使用相关推荐

  1. C语言使用CUDA中cufft函数做GPU加速FFT运算,与调用fftw函数的FFT做运算速度对比

    目录 任务介绍 环境所需相关软件下载与安装 C语言:不调用库的GPU加速FFT代码 C语言:调用fftw库的未使用GPU的FFT代码 C语言:调用cufft库的GPU加速FFT gnuplot安装画图 ...

  2. CUDA实现FFT并行计算

    前言   本文是个人学习心得的分享,希望大家在阅读文章后能在评论中一起学习交流!另外还可以访问我的HelloCUDA仓库查看我在学习CUDA中写的一些demo程序. 内容概要 复数的CUDA C++实 ...

  3. CUDA中grid、block、thread、warp与SM、SP的关系

    首先概括一下这几个概念.其中SM(Streaming Multiprocessor)和SP(streaming Processor)是硬件层次的,其中一个SM可以包含多个SP.thread是一个线程, ...

  4. java如何给一个链表定义和传值_如何在CUDA中为Transformer编写一个PyTorch自定义层...

    如今,深度学习模型处于持续的演进中,它们正变得庞大而复杂.研究者们通常通过组合现有的 TensorFlow 或 PyTorch 操作符来发现新的架构.然而,有时候,我们可能需要通过自定义的操作符来实现 ...

  5. Cuda中Global memory中coalescing例程解释

    Global memory是cuda中最常见的存储类型,又叫做Device memory,位于Host主机区域上,它的生命周期是在整个Grid里面,大约具有500个cycle latency.在cud ...

  6. [原]CUDA中grid、block、thread、warp与SM、SP的关系

    [原]CUDA中grid.block.thread.warp与SM.SP的关系 2015-3-27阅读209 评论0 首先概括一下这几个概念.其中SM(Streaming Multiprocessor ...

  7. CUDA中的一些基本概念

    线程 线程是CUDA中并行程序的基本构建,一个线程就是程序中国的一个单一的执行流,就像一件衣服上的一块棉,一块块棉交织在一起组成衣服,同样 一个个线程组成成并行程序. 随着处理器的核越来越多,硬件可以 ...

  8. CUDA中并行规约(Parallel Reduction)的优化

    Parallel Reduction是NVIDIA-CUDA自带的例子,也几乎是所有CUDA学习者的的必看算法.在这个算法的优化中,Mark Harris为我们实现了7种不同的优化版本,将Bandwi ...

  9. CUDA中的复数定义、开内存空间以及运算

    最近在做时频混合域的全波形反演(FWI),用CUDA加速,要做复数运算,所以研究了一下CUDA中复数运算等.简单说一下CUDA中复数的基本应用. 在CUDA中用CUFFT的库来定义与运算复数,基本如下 ...

最新文章

  1. (转)使用 Spring缓存抽象 支持 EhCache 和 Redis 混合部署
  2. MongoDB 索引
  3. 亲历惊心48小时抢救35亿交易数据
  4. 自定义带DropDownTable的TextField(事件)
  5. socket 编程入门教程(一)TCP server 端:1、建模
  6. DataCleaner(4.5)第一章
  7. KDD Cup2020 正式开赛,天池诚邀各路豪杰来挑战!!
  8. 前端JS笔试面试题目
  9. 穹顶之下 众信金融邀您共植树助环保
  10. setwindowpos怎么改变z序_Windows转Mac——操作习惯的改变!
  11. 安装django步骤
  12. 配置Gitlab Push自动触发jenkins构建
  13. win10无法安装软件,点击大部分exe文件无反应,无提示(安装了火绒)
  14. 泛微E9 MVC开发
  15. 书到用时方恨少,一大波JS开发工具函数来了
  16. Excel在统计分析中的应用—第十二章—回归分析与预测-运用LINEST函数进行多元线性回归分析
  17. 服务器系统如何重装?
  18. python面向对象的特征_python 面向对象的三大特性
  19. 遭遇“windows已经阻止此软件因为无法验证发行者”
  20. 牛客练习赛51 C、勾股定理 只一边求另外两边 结论

热门文章

  1. 《技术的本质》2月24日part1
  2. IEEE作者中心!解决你的选刊,模板,选题,写做的一系列困难!!!拿走不谢!!!
  3. 我们常常意识不到问题的存在,直到有人解决了这些问题
  4. LeetCode7.整数反转 JavaScript
  5. Git中的有个致命的远程执行漏洞
  6. Linux 系统内存分析
  7. Bootstrap响应式布局以及栅格框架
  8. 1.3(java学习笔记)构造方法及重载
  9. WiFi万能钥匙发布iOS4.0新增骚扰电话拦截功能
  10. Java虚拟机9:Java类加载机制