CUFFT - 填充/初始化问题

时间:2011-04-01 08:38:56

标签: visual-c++ cuda fft cufft

我正在研究用于卷积FFT示例的Nvidia SDK(对于大内核),我知道傅里叶变换及其FFT实现背后的理论(至少是基础),但我无法弄清楚下面的代码是什么作用:

const int    fftH = snapTransformSize(dataH + kernelH - 1);
const int    fftW = snapTransformSize(dataW + kernelW - 1);

....//gpu initialization code

printf("...creating R2C & C2R FFT plans for %i x %i\n", fftH, fftW);
        cuf ftSafeCall( cufftPlan2d(&fftPlanFwd, fftH, fftW, CUFFT_R2C) );
        cufftSafeCall( cufftPlan2d(&fftPlanInv, fftH, fftW, CUFFT_C2R) );

    printf("...uploading to GPU and padding convolution kernel and input data\n");
        cutilSafeCall( cudaMemcpy(d_Kernel, h_Kernel, kernelH * kernelW * sizeof(float), cudaMemcpyHostToDevice) );
        cutilSafeCall( cudaMemcpy(d_Data,   h_Data,   dataH   * dataW *   sizeof(float), cudaMemcpyHostToDevice) );
        cutilSafeCall( cudaMemset(d_PaddedKernel, 0, fftH * fftW * sizeof(float)) );
        cutilSafeCall( cudaMemset(d_PaddedData,   0, fftH * fftW * sizeof(float)) );

        padKernel(
            d_PaddedKernel,
            d_Kernel,
            fftH,
            fftW,
            kernelH,
            kernelW,
            kernelY,
            kernelX
        );

        padDataClampToBorder(
            d_PaddedData,
            d_Data,
            fftH,
            fftW,
            dataH,
            dataW,
            kernelH,
            kernelW,
            kernelY,
            kernelX
        );

之前我从未使用过CUFFT库所以我不知道snapTransformSize会做什么

(这是代码)

int snapTransformSize(int dataSize){
    int hiBit;
    unsigned int lowPOT, hiPOT;

    dataSize = iAlignUp(dataSize, 16);

    for(hiBit = 31; hiBit >= 0; hiBit--)
        if(dataSize & (1U << hiBit)) break;

    lowPOT = 1U << hiBit;
    if(lowPOT == dataSize)
        return dataSize;

    hiPOT = 1U << (hiBit + 1);
    if(hiPOT <= 1024)
        return hiPOT;
    else 
        return iAlignUp(dataSize, 512);
}

为什么复平面是如此初始化的。

请您提供解释链接或答案吗?

2 个答案:

答案 0 :(得分:2)

似乎将FFT维度四舍五入到下一个2的幂,除非维度超过1024,在这种情况下它会向上舍入到512的下一个倍数。

将FFT大小四舍五入后,您当然需要用零填充数据,以使其成为FFT的正确大小。

请注意,我们通常需要向上舍入并填充卷积的原因是因为每个FFT维度需要为image_dimension + kernel_dimension - 1,这通常不是一个方便的数字,例如2的幂。

答案 1 :(得分:1)

@Paul R所说的是正确的。为什么这样做是因为快速傅立叶变换操作 要求以最快的速度执行两个中的多个。请参阅Cooley-Tukey algorithm

只需确保您声明的矩阵是2的幂,您就不需要这种通用的安全实现。