【问题标题】:CUDA Inverse FFT BugCUDA 逆 FFT 错误
【发布时间】:2013-05-22 19:27:18
【问题描述】:

我有以下代码在执行逆 FFT 时有错误。当我打印输出并验证它时,前向 FFT 起作用。但反过来似乎没有。有任何想法吗?看起来我错过了一个概念吗?

代码 - http://pastebin.com/iZYtdcqR

编辑 - 我基本上重写了 CUDA 工具包示例附带的代码。我正在尝试使用 FFT 但使用修改后的算法(实际上是 DIF)执行卷积。

EDIT2 - 为问题添加代码。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

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

typedef enum signaltype {REAL, COMPLEX} signal;

typedef float2 Complex;

void
printData(Complex *a, int size, char *msg) {

  if (msg == "") printf("\n");
  else printf("%s\n", msg);

  for (int i = 0; i < size; i++)
    printf("%f %f\n", a[i].x, a[i].y);
}

void
normData(Complex *a, int size, float norm) {

  for (int i = 0; i < size; i++) {
    a[i].x /= norm;
    a[i].y /= norm;
  }
}

void
randomFill(Complex *h_signal, int size, int flag) {

  // Real signal.
  if (flag == REAL) {
    for (int i = 0; i < size; i++) {
      h_signal[i].x = rand() / (float) RAND_MAX;
      h_signal[i].y = 0;
    }
  }
}

// FFT a signal that's on the _DEVICE_.
void
signalFFT(Complex *d_signal, int signal_size) {

  cufftHandle plan;
  if (cufftPlan1d(&plan, signal_size, CUFFT_C2C, 1) != CUFFT_SUCCESS) {
    printf("Failed to plan FFT\n");
    exit(0);
  }

  // Execute the plan.
  if (cufftExecC2C(plan, (cufftComplex *) d_signal, (cufftComplex *) d_signal, CUFFT_FORWARD) != CUFFT_SUCCESS) {
    printf ("Failed Executing FFT\n");
    exit(0);
  }

}

void
signalIFFT(Complex *d_signal, int signal_size) {

  cufftHandle plan;
  if (cufftPlan1d(&plan, signal_size, CUFFT_C2C, 1) != CUFFT_SUCCESS) {
    printf("Failed to plan IFFT\n");
    exit(0);
  }

  // Execute the plan.
  if (cufftExecC2C(plan, (cufftComplex *) d_signal, (cufftComplex *) d_signal, CUFFT_INVERSE) != CUFFT_SUCCESS) {
    printf ("Failed Executing IFFT\n");
    exit(0);
  }

}

int main()
{

  Complex *h_signal, *d_signal1;

  int alloc_size, i;

  alloc_size = 16;

  // Kernel Block and Grid Size.
  const dim3 blockSize(16, 16, 1);
  const dim3 gridSize(alloc_size / 16 + 1, alloc_size / 16 + 1, 1);

  h_signal = (Complex *) malloc(sizeof(Complex) * alloc_size);

  cudaMalloc(&d_signal1, sizeof(Complex) * alloc_size);
  if (cudaGetLastError() != cudaSuccess){
    printf("Cuda error: Failed to allocate\n");
    exit(0);
  }
  //cudaMalloc(&d_signal2, sizeof(Complex) * alloc_size);

  // Add random data to signal.
  randomFill(h_signal, alloc_size, REAL);
  printData(h_signal, alloc_size, "Random H1");

  cudaMemcpy(d_signal1, h_signal, sizeof(Complex) * alloc_size, cudaMemcpyHostToDevice);

  signalFFT(d_signal1, alloc_size);

  signalIFFT(d_signal1, alloc_size);

  cudaDeviceSynchronize();

  cudaMemcpy(h_signal, d_signal1, sizeof(Complex) * alloc_size, cudaMemcpyDeviceToHost);

  printData(h_signal, alloc_size, "IFFT");

  return 0;
}

【问题讨论】:

    标签: cuda fft ifft


    【解决方案1】:

    写出好问题的建议:

    • 在问题中发布您的代码,而不是在外部链接中。有一天,该链接将失效,您对未来读者的问题也将失效。
    • 在问题中发布您的实际数据(在这种情况下没有那么多)。
    • 发布或确定您对数据的期望以及原因。

    另一个说明:

    • 袖带文档instructs you to use cufftComplex,不是您自己的数据类型,尽管您的工作正常。如果 cufft 的开发人员出于某种奇怪的原因更改了他们的数据布局,那么您的代码将在重新编译时中断。如果您使用推荐的数据类型,则不应该这样做。

    现在关于您的问题,我运行了您的代码并得到了如下结果:

    Random H1
    0.840188 0.000000
    0.394383 0.000000
    0.783099 0.000000
    0.798440 0.000000
    0.911647 0.000000
    0.197551 0.000000
    0.335223 0.000000
    0.768230 0.000000
    0.277775 0.000000
    0.553970 0.000000
    0.477397 0.000000
    0.628871 0.000000
    0.364784 0.000000
    0.513401 0.000000
    0.952230 0.000000
    0.916195 0.000000
    IFFT
    13.443005 0.000000
    6.310127 -0.000000
    12.529589 0.000000
    12.775041 0.000000
    14.586359 -0.000000
    3.160823 0.000000
    5.363565 0.000000
    12.291674 -0.000000
    4.444397 -0.000000
    8.863521 0.000000
    7.638353 0.000000
    10.061934 -0.000000
    5.836554 0.000000
    8.214415 -0.000000
    15.235678 -0.000000
    14.659121 -0.000000
    

    您的代码中似乎唯一缺少的是,您没有将结果除以转换的长度(在本例中为 16)来取回原始数据(如示例代码 @987654322 中所建议的那样) @)。当我这样做时,我会得到我认为预期的结果:

    Random H1
    0.840188 0.000000
    0.394383 0.000000
    0.783099 0.000000
    0.798440 0.000000
    0.911647 0.000000
    0.197551 0.000000
    0.335223 0.000000
    0.768230 0.000000
    0.277775 0.000000
    0.553970 0.000000
    0.477397 0.000000
    0.628871 0.000000
    0.364784 0.000000
    0.513401 0.000000
    0.952230 0.000000
    0.916195 0.000000
    IFFT
    0.840188 0.000000
    0.394383 -0.000000
    0.783099 0.000000
    0.798440 0.000000
    0.911647 -0.000000
    0.197551 0.000000
    0.335223 0.000000
    0.768230 -0.000000
    0.277775 -0.000000
    0.553970 0.000000
    0.477397 0.000000
    0.628871 -0.000000
    0.364785 0.000000
    0.513401 -0.000000
    0.952230 -0.000000
    0.916195 -0.000000
    

    顺便说一句,感谢提供了一个完整的、可编译的代码示例。

    【讨论】:

    • 感谢您的发现。不是一个真正的数学家,cuda 文档让我不知所措。将修复代码链接和数据,你的真棒答案有它:D
    • 似乎发生了一些有趣的事情。我不断收到这些瞬态运行时逻辑错误。很多次,当我尝试将填充数据添加到信号并尝试 fft 时,我得到了奇怪的答案,当我过了一会儿回来并再次运行程序时,它工作并匹配了我的参考输出。有什么重置内存的技巧或类似的东西吗?
    • 除非你有某种不稳定的设置(不稳定的硬件、软件损坏),否则没有必要重置内存或类似的东西。您的观察和问题可能最好发布一个新问题。尝试像这样在 cmets 中钻取某些东西是很困难的。
    • 我同意,但我真的无法复制它。我有输出日志,但没有运行的相应代码。
    猜你喜欢
    • 2012-04-30
    • 1970-01-01
    • 1970-01-01
    • 2018-07-12
    • 2015-11-15
    • 2018-03-16
    • 2013-03-10
    • 2011-08-09
    • 2015-08-20
    相关资源
    最近更新 更多