cufftPlanMany参数说明

背景

最近在看cufft这个库,传统的cufftPlan3d()这种plan接口逐渐被nvidia舍弃了,说是要用最新的cufftPlanMany,这个函数呢又依赖一个什么Advanced Data Layout(地址),最终把这个api搞得乌烟瘴气很难理解,为了理解自己写了一些测试来验证各个参数的意思,这里简单做一下总结。下面是函数声明以及对应的参数解释,看不懂的话可以结合后面的例子琢磨琢磨。

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

在这里插入图片描述

1D

先说说这函数能干啥,因为对于很多信号而言是需要采样的,对于搞过信号的同学理解起来比较方便,比如来了一串信号a=[0,1,2,3,4,5,6,7,8,9], 如果采样频率是2,那么就会得到b=[0,2,4,6,8]长度为5的信号,搁在以前,你要做fft的话,你需要自己提前写好代码把b摘出来,但是现在不需要了,直接用a信号就可以,nv把这个工作做了,具体如下:

//一维不饶很好理解
int rank = 1, 
int n[] = {5}, //这个值代表这个维度的fft()的采样后信号长度 
int inembed[] = {10}, //代表这个维度的输入信号长度
int istride = 2, // 代表采样步长<可以理解为采样频率>,这个就很蠢,每个维度<2维,3维下>必须一样
int idist = 10, // 一个batch的原始信号长度,一般是等于inembed, 
//但有时候需要截取一部分原始信号作为输入信号,所以是小于等于inembed尺寸
int onembed[] = 5, //同上
int ostride = 1, //同上
int odist = 5,  //同上
int batch = 1;

图示如下,这里没有画输出,意思和输入一样,接下来做个实验试试。
在这里插入图片描述
根据上面的例子可以知道,dist代表batch的大小,尺寸一定要大于nembed的。一个简单的的是代码如下:

#include <stdio.h>
#include <cuda_runtime.h>
#include <cufft.h>

int main() {
    cufftHandle plan;
    cufftComplex *data;
    cufftComplex *d_data;
    const int batch_n = 2;
    int idist_n = 11;
    cudaMalloc(&d_data, sizeof(cufftComplex) * idist_n * batch_n);
    data = (cufftComplex *)malloc(sizeof(cufftComplex) * idist_n * batch_n);

    for (int i = 0; i < 11; ++i) {
            data[i].x = i;
            data[i].y = 0;
            printf("(%f, %f) ",data[i].x, data[i].y);
    };
    printf("\n");
    for (int i = 11; i < 22; ++i) {
            data[i].x = i - 1;
            data[i].y = 0;
            printf("(%f, %f) ",data[i].x, data[i].y);
    };
    printf("\n");

    cudaMemcpy(d_data, data, sizeof(cufftComplex) * idist_n * batch_n, cudaMemcpyHostToDevice);

    int n[1] = { 5 }; // 1D FFT 尺寸
    int inembed[] = { 10 }; // 
    int istride = 2; // 
    int idist = idist_n; //
    int onembed[] = { 8};
    int ostride = 1; // 
    int odist =   10; // 
    cufftPlanMany(&plan, 1, n, inembed, istride, idist, onembed, ostride, odist, CUFFT_C2C, batch_n);

    cufftExecC2C(plan, d_data, d_data, CUFFT_FORWARD);

    cudaMemcpy(data, d_data, sizeof(cufftComplex) * batch_n * idist_n, cudaMemcpyDeviceToHost);

    printf("FFT result:\n");
    for (int i = 0; i < batch_n; ++i) {
        for (int j = 0; j < idist_n; ++j) {
            int idx = i * idist_n + j;
            printf("(%f, %f)\t", data[idx].x, data[idx].y);
        }
        printf("\n");
    }

    cufftDestroy(plan);
    cudaFree(d_data);
    free(data);

    return 0;
}

2D

2d的话其实本质和上面一样,但是采样却很蠢,只有stride只有一个大小,也就是横竖的采样步长一样。
在这里插入图片描述

3D

3D的数据数据排布有点反常,一般3d数据都是正视图的那一个平面先排满后,再排第二个切面,但是这里是先排满一个俯视图平面后,再排下一个切面,这里的embed_2=Nz, embed_1=ny, embed_0 = nx, 如下图,图中的坐标系是我们经常使用的方式。
在这里插入图片描述

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值