1.使用cufftHandle
创建句柄
2.使用cufftPlan1d()
,cufftPlan3d()
,cufftPlan3d()
,cufftPlanMany()
对句柄进行配置,主要是配置句柄对应的信号长度,信号类型,在内存中的存储形式等信息。
cufftPlan1d()
:针对单个 1 维信号
cufftPlan2d()
:针对单个 2 维信号
cufftPlan3d()
:针对单个 3 维信号
cufftPlanMany()
:针对多个信号同时进行 fft
3.使用cufftExec()
函数执行 fft
4.使用cufftDestroy()
函数释放 GPU 资源
假设要执行 fft 的信号data_dev
的长度为N
,并且已经传输到 GPU 显存中,data_dev
数据的类型为cufftComplex
,可以用一下方式产生主机段的data_dev。
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_C2C
为要执行 fft 的信号输入类型及输出类型都为复数;CUFFT_C2R
表示输入复数,输出实数;CUFFT_R2C
表示输入实数,输出复数;CUFFT_R2R
表示输入实数,输出实数;BATCH
表示要执行 fft 的信号的个数,新版的已经使用cufftPlanMany()
来同时完成多个信号的 fft。cufftExecC2C()
:
CUFFT_FORWARD
表示执行的是 fft 正变换;CUFFT_INVERSE
表示执行 fft 逆变换。需要注意的是,执行完逆 fft 之后,要对信号中的每个值乘以 1/N
#include
#include
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include
#define NX 3335 // 有效数据个数
#define N 5335 // 补0之后的数据长度
#define BATCH 1
#define BLOCK_SIZE 1024
using std::cout;
using std::endl;
/**
* 功能:判断两个 cufftComplex 数组的是否相等
* 输入:idataA 输入数组A的头指针
* 输入:idataB 输出数组B的头指针
* 输入:size 数组的元素个数
* 返回:true | false
*/
bool IsEqual(cufftComplex *idataA, cufftComplex *idataB, const int size)
{
for (int i = 0; i < size; i++)
{
if (abs(idataA[i].x - idataB[i].x) > 0.000001 || abs(idataA[i].y - idataB[i].y) > 0.000001)
return false;
}
return true;
}
/**
* 功能:实现 cufftComplex 数组的尺度缩放,也就是乘以一个数
* 输入:idata 输入数组的头指针
* 输出:odata 输出数组的头指针
* 输入:size 数组的元素个数
* 输入:scale 缩放尺度
*/
static __global__ void cufftComplexScale(cufftComplex *idata, cufftComplex *odata, const int size, float scale)
{
const int threadID = blockIdx.x * blockDim.x + threadIdx.x;
if (threadID < size)
{
odata[threadID].x = idata[threadID].x * scale;
odata[threadID].y = idata[threadID].y * scale;
}
}
int main()
{
cufftComplex *data_dev; // 设备端数据头指针
cufftComplex *data_Host = (cufftComplex*)malloc(NX*BATCH * sizeof(cufftComplex)); // 主机端数据头指针
cufftComplex *resultFFT = (cufftComplex*)malloc(N*BATCH * sizeof(cufftComplex)); // 正变换的结果
cufftComplex *resultIFFT = (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;
}
dim3 dimBlock(BLOCK_SIZE); // 线程块
dim3 dimGrid((NX + BLOCK_SIZE - 1) / dimBlock.x); // 线程格
cufftHandle plan; // 创建cuFFT句柄
cufftPlan1d(&plan, N, CUFFT_C2C, BATCH);
// 计时
clock_t start, stop;
double duration;
start = clock();
cudaMalloc((void**)&data_dev, sizeof(cufftComplex)*N*BATCH); // 开辟设备内存
cudaMemset(data_dev, 0, sizeof(cufftComplex)*N*BATCH); // 初始为0
cudaMemcpy(data_dev, data_Host, NX * sizeof(cufftComplex), cudaMemcpyHostToDevice); // 从主机内存拷贝到设备内存
cufftExecC2C(plan, data_dev, data_dev, CUFFT_FORWARD); // 执行 cuFFT,正变换
cudaMemcpy(resultFFT, data_dev, N * sizeof(cufftComplex), cudaMemcpyDeviceToHost); // 从设备内存拷贝到主机内存
cufftExecC2C(plan, data_dev, data_dev, CUFFT_INVERSE); // 执行 cuFFT,逆变换
cufftComplexScale << > > (data_dev, data_dev, N, 1.0f / N); // 乘以系数
cudaMemcpy(resultIFFT, data_dev, NX * sizeof(cufftComplex), cudaMemcpyDeviceToHost); // 从设备内存拷贝到主机内存
stop = clock();
duration = (double)(stop - start) * 1000 / CLOCKS_PER_SEC;
cout << "时间为 " << duration << " ms" << endl;
cufftDestroy(plan); // 销毁句柄
cudaFree(data_dev); // 释放空间
cout << IsEqual(data_Host, resultIFFT, NX) << endl;
return 0;
}
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include
#include
#include
#include
using namespace std;
using namespace cv;
#define COLS 3
#define ROWS 3
extern "C" void iteration_mat1()
{
cufftComplex *result_temp_din = (cufftComplex*)malloc(COLS*ROWS * sizeof(cufftComplex));
cufftHandle p;
//输入赋值数据
for (size_t j = 0; j < ROWS; j++)
{
for (size_t i = 0; i < COLS; i++)
{
result_temp_din[i + j*COLS].x = (i + 1)*(j + 1);
cout << result_temp_din[i + j*COLS].x << " ";
result_temp_din[i + j*COLS].y = 0;
}
}
cout << endl;
size_t pitch;
cufftComplex *t_result_temp_din;
cudaMallocPitch((void**)&t_result_temp_din, &pitch, COLS * sizeof(cufftComplex), ROWS);
cufftComplex *t_result_temp_out;
cudaMallocPitch((void**)&t_result_temp_out, &pitch, COLS * sizeof(cufftComplex), ROWS);
//将值辅到Device
//cudaMemcpy2D(t_result_temp_din, pitch, result_temp_din, COLS * sizeof(cufftComplex), COLS * sizeof(cufftComplex), ROWS, cudaMemcpyHostToDevice);
cudaMemcpy(t_result_temp_din,result_temp_din, ROWS * sizeof(cufftComplex)* COLS, cudaMemcpyHostToDevice);
//forward fft 制定变换规则
cufftPlan2d(&p, ROWS, COLS, CUFFT_C2C);
//执行变换
cufftExecC2C(p, (cufftComplex*)t_result_temp_din, (cufftComplex*)t_result_temp_out, CUFFT_FORWARD);
//将值辅到host
cudaMemcpy(result_temp_din, t_result_temp_out, ROWS * sizeof(cufftComplex)* COLS, cudaMemcpyDeviceToHost);
//cudaMemcpy2D(result_temp_din, pitch, t_result_temp_out, COLS * sizeof(cufftComplex), sizeof(cufftComplex)* ROWS, COLS, cudaMemcpyDeviceToHost);
//提取实部和虚部
for (size_t j = 0; j < ROWS; j++)
{
for (size_t i = 0; i < COLS; i++)
{
cout << result_temp_din[i + j*COLS].x << " ";//实部
cout << result_temp_din[i + j*COLS].y << endl;//虚部
}
}
}
注: cufftPlan2d(&p, ROWS, COLS, CUFFT_C2C); 看清楚rows和cols,千万别出错!
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include
#include
#include
#include
using namespace std;
using namespace cv;
#define COLS 3
#define ROWS 3
extern "C" void iteration_mat1()
{
cufftComplex *result_temp_din = (cufftComplex*)malloc(COLS*ROWS * sizeof(cufftComplex));
cufftHandle p;
//输入赋值数据
for (size_t j = 0; j < ROWS; j++)
{
for (size_t i = 0; i < COLS; i++)
{
result_temp_din[i + j*COLS].x = (i + 1)*(j + 1);
cout << result_temp_din[i + j*COLS].x << " ";
result_temp_din[i + j*COLS].y = 0;
}
}
cout << endl;
size_t pitch;
cufftComplex *t_result_temp_din;
cudaMallocPitch((void**)&t_result_temp_din, &pitch, COLS * sizeof(cufftComplex), ROWS);
cufftComplex *t_result_temp_out;
cudaMallocPitch((void**)&t_result_temp_out, &pitch, COLS * sizeof(cufftComplex), ROWS);
//将值辅到Device
//cudaMemcpy2D(t_result_temp_din, pitch, result_temp_din, COLS * sizeof(cufftComplex), COLS * sizeof(cufftComplex), ROWS, cudaMemcpyHostToDevice);
cudaMemcpy(t_result_temp_din,result_temp_din, ROWS * sizeof(cufftComplex)* COLS, cudaMemcpyHostToDevice);
//forward fft 制定变换规则
cufftPlan2d(&p, ROWS, COLS, CUFFT_C2C);
//执行变换
cufftExecC2C(p, (cufftComplex*)t_result_temp_din, (cufftComplex*)t_result_temp_out, CUFFT_FORWARD);
//将值辅到host
cudaMemcpy(result_temp_din, t_result_temp_out, ROWS * sizeof(cufftComplex)* COLS, cudaMemcpyDeviceToHost);
//cudaMemcpy2D(result_temp_din, pitch, t_result_temp_out, COLS * sizeof(cufftComplex), sizeof(cufftComplex)* ROWS, COLS, cudaMemcpyDeviceToHost);
//提取实部和虚部
for (size_t j = 0; j < ROWS; j++)
{
for (size_t i = 0; i < COLS; i++)
{
cout << result_temp_din[i + j*COLS].x << " ";//实部
cout << result_temp_din[i + j*COLS].y << endl;//虚部
}
}
}
转载:https://www.cnblogs.com/aiguona/p/9485606.html