managedCUDA:使用1D FFT

时间:2014-08-20 15:07:34

标签: c# cuda

我正在尝试用C#中的CUDA实现信号的FFT变换。我正在使用managedCUDA库。我已经实现了它,但它看起来很糟糕,根本没有效率。

这是我的工作代码:

public static float[] doFFT(float[] data)
{
    CudaContext cntxt = new CudaContext();
    CudaDeviceVariable<float2> devData = new CudaDeviceVariable<float2>(data.Length);
    float2[] fData = new float2[data.Length];

    for (int i = 0; i < data.Length; i++)
    {
        fData[i].x = data[i];
    }

    devData.CopyToDevice(fData);
    CudaFFTPlanMany fftPlan = new CudaFFTPlanMany(1, new int[] { data.Length }, 1, cufftType.R2C);

    fftPlan.Exec(devData.DevicePointer, TransformDirection.Forward);

    float2[] result = new float2[data.Length];
    devData.CopyToHost(result);

    fftPlan.Dispose();
    float[][] res = new float[2][];
    res[0] = new float[data.Length];
    res[1] = new float[data.Length];
    for (int i = 0; i < data.Length; i++)
    {
        res[0][i] = result[i].x;
        res[1][i] = result[i].y;
    }

    return res[0];
}

如何避免手动将信号数据复制到float2数组中?如何避免将复杂数据反向复制到单维浮点数组中(只是复数的实部)?

我试过在那里复制:

CudaDeviceVariable<float> devData = data;

因为我找到了某个地方,但结果却是错误的: - /

非常感谢!

尤拉伊

1 个答案:

答案 0 :(得分:2)

如果您正在进行R2C就地FFT,则需要将输入数组填充到正确的大小。另见CUFFT文档,第2.4章。数据布局,第6页。无需在主机端进行转换。 以下示例代码应指向正确的方向,而不是完整的,例如,最后没有清理......

//Context creation not necessary if CudaFFTPlan is the first Cuda related call
//Cufft creates a new context if none exists and we can use it implicitly afterwards
//CudaContext ctx = new CudaContext();

float[] h_dataIn = new float[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };

//Caution: Array sizes matter! See CUFFFT-Documentation...
int size_real = h_dataIn.Length;
int size_complex = (int)Math.Floor(size_real / 2.0) + 1;

CudaFFTPlanMany fftPlan = new CudaFFTPlanMany(1, new int[] { size_real }, 1, cufftType.R2C);

//Size of d_data must be padded for inplace R2C transforms: size_complex * 2 and not size_real
CudaDeviceVariable<float> d_data = new CudaDeviceVariable<float>(size_complex * 2);

//device allocation and host have different sizes, why the amount of data must be given explicitly for copying:
d_data.CopyToDevice(h_dataIn, 0, 0, size_real * sizeof(float));

//executa plan
fftPlan.Exec(d_data.DevicePointer, TransformDirection.Forward);

//Output to host, either as float2 or float, but array sizes must be right!
float2[] h_dataOut  = new float2[size_complex];
float[] h_dataOut2 = new float[size_complex * 2];
d_data.CopyToHost(h_dataOut);
d_data.CopyToHost(h_dataOut2);