CUFFT库(cufft_C2C,cufft_R2C,cufft_C2R,cufft_Z2C,cufft_D2Z,cufft_Z2D)
CUDA的cufft库可以实现(复数C-复数C),(实数R-复数C)和(复数C-实数R)的单精度,双精度福利变换。其变换前后的输入,输出数据的长度如图所示。在C2R和R2C模式中,根据埃尔米特对称性(Hermitian symmetry),变换后,*代表共轭复数。CUFFT的傅里叶变换类型则利用了这些冗余,将计算量降到最低。
注意:下表都是单精度(C-表示float复数,R表示float实数)。而双精度标识(Z表示double复数,D表示double实数)
下面分别给出示例程序:
(1)C2C(Z2Z)模式
1.单精度代码
#include"iostream"
#include"cuda_runtime_api.h"
#include"device_launch_parameters.h"
#include"cufft.h"
using namespace std;
//FFT反变换后,用于规范化的函数
__global__ void normalizing(cufftComplex* data, int data_len)
{int idx = blockDim.x*blockIdx.x + threadIdx.x;data[idx].x /= data_len;data[idx].y /= data_len;
}
void Check(cudaError_t status)
{if (status != cudaSuccess){cout << "行号:" << __LINE__ << endl;cout << "错误:" << cudaGetErrorString(status) << endl;}
}
int main()
{const int Nt = 256;const int BATCH = 1;//BATCH用于批量处理一批一维数据,当BATCH=2时//则将0-1024,1024-2048作为两个一维信号做FFT处理变换cufftComplex* host_in, *host_out, *device_in, *device_out;//主机内存申请及初始化--主机锁页内存Check(cudaMallocHost((void**)&host_in, Nt * sizeof(cufftComplex)));Check(cudaMallocHost((void**)&host_out, Nt * sizeof(cufftComplex)));for (int i = 0; i < Nt; i++){host_in[i].x = i + 1;host_in[i].y = i + 1;}//设备内存申请Check(cudaMalloc((void**)&device_in, Nt * sizeof(cufftComplex)));Check(cudaMalloc((void**)&device_out, Nt * sizeof(cufftComplex)));//数据传输--H2DCheck(cudaMemcpy(device_in, host_in, Nt * sizeof(cufftComplex), cudaMemcpyHostToDevice));//创建cufft句柄cufftHandle cufftForwrdHandle, cufftInverseHandle;cufftPlan1d(&cufftForwrdHandle, Nt, CUFFT_C2C, BATCH);cufftPlan1d(&cufftInverseHandle, Nt, CUFFT_C2C, BATCH);//执行fft正变换cufftExecC2C(cufftForwrdHandle, device_in, device_out, CUFFT_FORWARD);//数据传输--D2HCheck(cudaMemcpy(host_out, device_out, Nt * sizeof(cufftComplex), cudaMemcpyDeviceToHost));//设置输出精度--正变换结果输出cout << "正变换结果:" << endl;cout.setf(20);for (int i = 0; i < Nt; i++){cout << host_out[i].x << "+j*" << host_out[i].y << endl;}//执行fft反变换cufftExecC2C(cufftInverseHandle, device_out, device_in, CUFFT_INVERSE);//IFFT结果是真值的N倍,因此要做/N处理dim3 grid(Nt / 128);dim3 block(128);normalizing << <grid, block >> > (device_in, Nt);//数据传输--D2HCheck(cudaMemcpy(host_in, device_in, Nt * sizeof(cufftComplex), cudaMemcpyDeviceToHost));//设置输出精度--反变换结果输出cout << "反变换结果:" << endl;cout.setf(20);for (int i = 0; i < Nt; i++){cout << host_in[i].x << "+j*" << host_in[i].y << endl;}cin.get();return 0;
}
2.双精度代码
#include"iostream"
#include"cuda_runtime_api.h"
#include"device_launch_parameters.h"
#include"cufft.h"
using namespace std;
//FFT反变换后,用于规范化的函数
__global__ void normalizing(cufftDoubleComplex* data,int data_len)
{int idx = blockDim.x*blockIdx.x + threadIdx.x;data[idx].x /= data_len;data[idx].y /= data_len;
}
void Check(cudaError_t status)
{if (status != cudaSuccess){cout << "行号:" << __LINE__ << endl;cout << "错误:" << cudaGetErrorString(status) << endl;}
}
int main()
{const int Nt =256;const int BATCH = 1;//BATCH用于批量处理一批一维数据,当BATCH=2时//则将0-1024,1024-2048作为两个一维信号做FFT处理变换cufftDoubleComplex* host_in, *host_out, *device_in, *device_out;//主机内存申请及初始化--主机锁页内存Check(cudaMallocHost((void**)&host_in, Nt * sizeof(cufftDoubleComplex)));Check(cudaMallocHost((void**)&host_out, Nt * sizeof(cufftDoubleComplex)));for (int i = 0; i < Nt; i++){host_in[i].x = i + 1;host_in[i].y = i + 1;}//设备内存申请Check(cudaMalloc((void**)&device_in, Nt * sizeof(cufftDoubleComplex)));Check(cudaMalloc((void**)&device_out, Nt * sizeof(cufftDoubleComplex)));//数据传输--H2DCheck(cudaMemcpy(device_in, host_in, Nt * sizeof(cufftDoubleComplex), cudaMemcpyHostToDevice));//创建cufft句柄cufftHandle cufftForwrdHandle, cufftInverseHandle;cufftPlan1d(&cufftForwrdHandle, Nt, CUFFT_Z2Z, BATCH);cufftPlan1d(&cufftInverseHandle, Nt, CUFFT_Z2Z, BATCH);//执行fft正变换cufftExecZ2Z(cufftForwrdHandle, device_in, device_out, CUFFT_FORWARD);//数据传输--D2HCheck(cudaMemcpy(host_out, device_out, Nt * sizeof(cufftDoubleComplex), cudaMemcpyDeviceToHost));//设置输出精度--正变换结果输出cout << "正变换结果:" << endl;cout.setf(20);for (int i = 0; i < Nt; i++){cout << host_out[i].x<< "+j*" << host_out[i].y << endl;}//执行fft反变换cufftExecZ2Z(cufftInverseHandle, device_out, device_in, CUFFT_INVERSE);//IFFT结果是真值的N倍,因此要做/N处理dim3 grid(Nt/128); dim3 block(128);normalizing << <grid, block >> > (device_in,Nt);//数据传输--D2HCheck(cudaMemcpy(host_in, device_in, Nt * sizeof(cufftDoubleComplex), cudaMemcpyDeviceToHost));//设置输出精度--反变换结果输出cout << "反变换结果:" << endl;cout.setf(20);for (int i = 0; i < Nt; i++){cout << host_in[i].x << "+j*" << host_in[i].y << endl;}cin.get();return 0;
}
(2)R2C(D2Z)模式-双精度(单精度类似)&&C2R(Z2D)模式双精度(单精度类似) 包括正反变换
#include"iostream"
#include"cuda_runtime_api.h"
#include"device_launch_parameters.h"
#include"cufft.h"
using namespace std;
#define Check(call) \
{ \cudaError_t status = call; \if (status != cudaSuccess) \{ \cout << "行号:" << __LINE__ << endl; \cout << "错误:" << cudaGetErrorString(status) << endl; \} \
}//FFT反变换后,用于规范化的函数
__global__ void normalizing(cufftDoubleReal* data, int data_len)
{int idx = blockDim.x*blockIdx.x + threadIdx.x;if (idx<data_len){data[idx] /=(data_len);}
}int main()
{const int Nt =512;const int BATCH = 1;//BATCH用于批量处理一批一维数据,当BATCH=2时//则将0-511,512-1023作为两个一维信号做FFT处理变换cufftDoubleReal* host_in, *device_in;cufftDoubleComplex* host_out, *device_out;//主机内存申请及初始化--主机锁页内存Check(cudaMallocHost((void**)&host_in, Nt * sizeof(cufftDoubleReal)));//特别要注意:这里的输出长度变为(Nt/2+1)Check(cudaMallocHost((void**)&host_out, (Nt / 2 + 1) * sizeof(cufftDoubleComplex)));for (int i = 0; i < Nt; i++){host_in[i] = i + 1;}//设备内存申请Check(cudaMalloc((void**)&device_in, Nt * sizeof(cufftDoubleReal)));//特别要注意:这里的输出长度变为(Nt/2+1)Check(cudaMalloc((void**)&device_out, (Nt / 2 + 1) * sizeof(cufftDoubleComplex)));//数据传输--H2DCheck(cudaMemcpy(device_in, host_in, Nt * sizeof(cufftDoubleReal), cudaMemcpyHostToDevice));//创建cufft句柄cufftHandle cufftForwrdHandle, cufftInverseHandle;cufftPlan1d(&cufftForwrdHandle, Nt, CUFFT_D2Z, BATCH);cufftPlan1d(&cufftInverseHandle, Nt, CUFFT_Z2D, BATCH);//执行fft正变换cufftExecD2Z(cufftForwrdHandle, device_in, device_out);//由于D2Z的方向是固定的,无需填入参数//数据传输--D2HCheck(cudaMemcpy(host_out, device_out, (Nt/2+1) * sizeof(cufftDoubleComplex), cudaMemcpyDeviceToHost));//设置输出精度--正变换结果输出cout << "正变换结果:" << endl;cout.setf(20);for (int i = 0; i < (Nt / 2 + 1); i++){cout << host_out[i].x << "+j*" << host_out[i].y << endl;}//执行fft反变换cufftExecZ2D(cufftInverseHandle, device_out, device_in);//由于Z2D的方向是固定的,无需填入参数//IFFT结果是真值的N倍,因此要做/N处理dim3 grid(ceil((Nt / 2 + 1) / 128.0) + 1);dim3 block(128);normalizing << <grid, block >> > (device_in, Nt);//数据传输--D2HCheck(cudaMemcpy(host_in, device_in, Nt * sizeof(cufftDoubleReal), cudaMemcpyDeviceToHost));//设置输出精度--反变换结果输出cout << "反变换结果:" << endl;cout.setf(20);for (int i = 0; i < Nt; i++){cout << host_in[i] << endl;}cin.get();return 0;
}
CUFFT库(cufft_C2C,cufft_R2C,cufft_C2R,cufft_Z2C,cufft_D2Z,cufft_Z2D)相关推荐
- CUDA快速傅里叶变换 cuFFT
分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! CUDA ...
- C语言使用CUDA中cufft函数做GPU加速FFT运算,与调用fftw函数的FFT做运算速度对比
目录 任务介绍 环境所需相关软件下载与安装 C语言:不调用库的GPU加速FFT代码 C语言:调用fftw库的未使用GPU的FFT代码 C语言:调用cufft库的GPU加速FFT gnuplot安装画图 ...
- 2能不用cuda_cuda学习-1-cufft的使用
一.函数的定义与执行 一般的函数定义 void function(); cuda的函数定义 __global__ void function(); global前缀表明这个函数在哪里执行,由谁呼叫 g ...
- NVIDIA GPU的快速傅立叶变换
NVIDIA GPU的快速傅立叶变换 cuFFT库提供GPU加速的FFT实现,其执行速度比仅CPU的替代方案快10倍.cuFFT用于构建跨学科的商业和研究应用程序,例如深度学习,计算机视觉,计算物理, ...
- CUDA Samples目录
简介 Simple Reference 基础CUDA示例,适用于初学者, 反映了运用CUDA和CUDA runtime APIs的一些基本概念. Utilities Reference 演示如何查 ...
- 最牛逼的开源机器学习框架,你知道几个
最牛逼的开源机器学习框架,你知道几个 作者 大白鲸团队 关注 2015.12.29 20:16 字数 1829 阅读 3689评论 0喜欢 7 机器学习毫无疑问是当今最热的话题,它已经渗透到生活的方方 ...
- 避免关注底层硬件,Nvidia将机器学习与GPU绑定
Nvidia释放的一组cuDNN的库,有效的实现了其与多种深度学习框架的整合.基于cuDNN,加速了代码的运行,同时让研究员避免去关心底层硬件性能. 关键字: 编程语言语音识别Nvidia 原文链接: ...
- python gpu编程_Python笔记_第四篇_高阶编程_进程、线程、协程_5.GPU加速
Numba:高性能计算的高生产率 在这篇文章中,笔者将向你介绍一个来自Anaconda的Python编译器Numba,它可以在CUDA-capable GPU或多核cpu上编译Python代码.Pyt ...
- 28款GitHub最流行的开源机器学习项目,推荐GitHub上10 个开源深度学习框架
20 个顶尖的 Python 机器学习开源项目 机器学习 2015-06-08 22:44:30 发布 您的评价: 0.0 收藏 1收藏 我们在Github上的贡献者和提交者之中检查了用Python语 ...
最新文章
- [C++] Lvalue and Rvalue Reference
- Azure SQL 数据库最新版本现已提供预览版
- SQL Server 排序规则(摘)
- 八边形点坐标数的lisp_图形学入门第五课:齐次坐标
- java icon动态变换,以编程方式自动更改ImageIcon [Java]
- 剑指Offer面试题:30.第一个只出现一次的字符
- RTT线程管理篇——RTT时间片
- Oracle数据库基础1-数据类型与约束
- OAuth2.0学习(1-11)新浪开放平台微博认证-使用OAuth2.0调用微博的开放API
- ACR122U-A9|ACR1251|ACM1252系列NFC读写器读卡器PCSC Tool测试工具使用步骤说明
- 谈谈我选择VC界面皮肤库的标准
- smobiler中实现页面切换_使用Smobiler实现类似美团的界面
- ios10 申请拍照权限_iOS 10 获取相册相机权限
- 安卓日历每日提醒_好用的安卓日历Jorte:可添加待办事项和提醒
- Python 利用多线程进行爬虫(一)
- Windows系统远程连接Linux系统操作
- 4.3 协方差及相关系数、矩
- HASH和HMAC(3):SHA-1算法原理
- cin.tie(0)和ios::sync_with_stdio(false)
- 医药保健行业crm系统有何特色