FFT 的实际输入然后 iFFT 返回一维数组中的实际数据
Real input to FFT then iFFT back to real data in 1-D Array
我正在尝试使用英特尔 MKL 实现 FFT 和 iFFT。实际输入的 FFT 工作正常,我得到的输出数组是正确的。在对 iFFT 使用相同的输出数组时,返回的值都乘以数组的大小,这对所有大小都适用。我不明白为什么会这样。代码如下:
size_t size;
std::cout << "enter the size of input and output array: ";
std::cin >> size;
float *inp = NULL;
MKL_Complex8 *op = NULL;
MKL_LONG status;
// Allocate memory for the arrays.
inp = (float*) mkl_malloc(size*sizeof(float), 64);
op = (MKL_Complex8*) mkl_malloc((size/2+1)*sizeof(MKL_Complex8), 64);
//Initialize values of input
for (size_t i = 0; i < size; i++){
if(i < 8)
inp[i] = -std::rand()%10;
else if(i ==8)
inp[i] = 0;
else
inp[i] = std::rand()%10;
}
std::cout << "The input array is: " << std::endl;
for (size_t i = 0; i < size; i++){
std::cout << inp[i] << ", ";
}
std::cout << std::endl;
//Specify descriptor values.
DFTI_DESCRIPTOR_HANDLE hand = NULL;
status = DftiCreateDescriptor(&hand, DFTI_SINGLE, DFTI_REAL, 1, (MKL_LONG) size);
status = DftiSetValue(hand, DFTI_PLACEMENT, DFTI_NOT_INPLACE);
status = DftiSetValue(hand, DFTI_CONJUGATE_EVEN_STORAGE, DFTI_COMPLEX_COMPLEX);
status = DftiSetValue(hand, DFTI_PACKED_FORMAT, DFTI_CCE_FORMAT);
status = DftiCommitDescriptor(hand);
status = DftiComputeForward(hand, inp, op);
status = DftiComputeBackward(hand, op, inp);
std::cout << "\nThe output of iFFT is: " << std::endl;
for (size_t i = 0; i < size; i++){
std::cout << inp[i] << ", ";
}
std::cout << std::endl;
DftiFreeDescriptor(&hand);
free(inp);
free(op);
return 0;
}
一个粗略的解决方法是在 iFFT 之后将单个数组元素除以大小,但这并不能解释为什么会发生这种情况。了解实际原因并加以纠正会好得多。这是在实际代码之前实现这些转换的尝试,我真的很想了解为什么会这样。谢谢
FFT/IFFT的定义存在不同的约定,具有不同的归一化因子:FFT侧1/N归一化,或IFFT侧1/N归一化,或两者1/sqrt(N)归一化边,或者根本没有标准化。
在没有归一化因子的情况下,在 FFT/IFFT 之后,您可以有效地乘以 FFT 大小。
正如 Cris Luengo 在评论中提到的,MKL 很可能选择提供没有规范化的构建块,以免因规范化两次而受到惩罚。
在英特尔 MKL 的上下文中,存在 2 个参数 DFTI_FORWARD_SCALE 和 DFTI_BACKWARD_SCALE,可以使用 DftiSetValue() 进行设置。对于 one-dimensional 变换,可以使用正向变换比例为 1,反向变换比例为 1/n,其中 'n' 是一维变换的大小。 (有关更多信息,请参阅 Intel documentation for MKL)
我正在尝试使用英特尔 MKL 实现 FFT 和 iFFT。实际输入的 FFT 工作正常,我得到的输出数组是正确的。在对 iFFT 使用相同的输出数组时,返回的值都乘以数组的大小,这对所有大小都适用。我不明白为什么会这样。代码如下:
size_t size;
std::cout << "enter the size of input and output array: ";
std::cin >> size;
float *inp = NULL;
MKL_Complex8 *op = NULL;
MKL_LONG status;
// Allocate memory for the arrays.
inp = (float*) mkl_malloc(size*sizeof(float), 64);
op = (MKL_Complex8*) mkl_malloc((size/2+1)*sizeof(MKL_Complex8), 64);
//Initialize values of input
for (size_t i = 0; i < size; i++){
if(i < 8)
inp[i] = -std::rand()%10;
else if(i ==8)
inp[i] = 0;
else
inp[i] = std::rand()%10;
}
std::cout << "The input array is: " << std::endl;
for (size_t i = 0; i < size; i++){
std::cout << inp[i] << ", ";
}
std::cout << std::endl;
//Specify descriptor values.
DFTI_DESCRIPTOR_HANDLE hand = NULL;
status = DftiCreateDescriptor(&hand, DFTI_SINGLE, DFTI_REAL, 1, (MKL_LONG) size);
status = DftiSetValue(hand, DFTI_PLACEMENT, DFTI_NOT_INPLACE);
status = DftiSetValue(hand, DFTI_CONJUGATE_EVEN_STORAGE, DFTI_COMPLEX_COMPLEX);
status = DftiSetValue(hand, DFTI_PACKED_FORMAT, DFTI_CCE_FORMAT);
status = DftiCommitDescriptor(hand);
status = DftiComputeForward(hand, inp, op);
status = DftiComputeBackward(hand, op, inp);
std::cout << "\nThe output of iFFT is: " << std::endl;
for (size_t i = 0; i < size; i++){
std::cout << inp[i] << ", ";
}
std::cout << std::endl;
DftiFreeDescriptor(&hand);
free(inp);
free(op);
return 0;
}
一个粗略的解决方法是在 iFFT 之后将单个数组元素除以大小,但这并不能解释为什么会发生这种情况。了解实际原因并加以纠正会好得多。这是在实际代码之前实现这些转换的尝试,我真的很想了解为什么会这样。谢谢
FFT/IFFT的定义存在不同的约定,具有不同的归一化因子:FFT侧1/N归一化,或IFFT侧1/N归一化,或两者1/sqrt(N)归一化边,或者根本没有标准化。
在没有归一化因子的情况下,在 FFT/IFFT 之后,您可以有效地乘以 FFT 大小。
正如 Cris Luengo 在评论中提到的,MKL 很可能选择提供没有规范化的构建块,以免因规范化两次而受到惩罚。
在英特尔 MKL 的上下文中,存在 2 个参数 DFTI_FORWARD_SCALE 和 DFTI_BACKWARD_SCALE,可以使用 DftiSetValue() 进行设置。对于 one-dimensional 变换,可以使用正向变换比例为 1,反向变换比例为 1/n,其中 'n' 是一维变换的大小。 (有关更多信息,请参阅 Intel documentation for MKL)