我正在尝试用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;
因为我找到了某个地方,但结果却是错误的: - /
非常感谢!
尤拉伊
答案 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);