Neon IFFT与Python的NumPy IFFT相比-为什么结果不同?

问题描述

作为开发工作的一部分,我们使用Python 3.8(使用NumPy 1.19)开发算法。然后,我们使用C NE10库在neon中实现它。 在一个阶段中,我们使用内置的IFFT函数计算傅立叶逆变换。 当我们在neon (NE10)(最新版本)IFFT和Python的NumPy 1.19 IFFT之间进行比较时,我们得到了不同的结果(它们相差不大,但相差远远大于数值精度,请参见下面的输出)。 / p>

Python代码

import numpy as np

nfft = 4096
FREQUENCY_BINS = 2049
NUMBER_OF_OUTPUTS = 4

in02_IFFT = np.zeros((nfft,NUMBER_OF_OUTPUTS))*(0+0j)

# Generating the input
half = np.zeros((FREQUENCY_BINS,NUMBER_OF_OUTPUTS))*(0+0j)
  for n in range(FREQUENCY_BINS):
    half[n,:] = n % 8 + (n % 4)*1j
    
# Taking symmetric conjugate for the other half so the output will be real
mirror = np.flip( np.conj(half[1:-1,:]),axis=0 ) # mirror-reflect frequencies
in02_IFFT = np.vstack((half,mirror)) 

 out02_IFFT = np.ones((nfft,NUMBER_OF_OUTPUTS))*(1+0j)
 for i in range(NUMBER_OF_OUTPUTS):
    out02_IFFT[:,i] = np.fft.ifft(in02_IFFT[:,i])

 print(in02_IFFT[0:12,0])
 print(out02_IFFT[0:12,0])

以下是前12个条目的输出

Input[0:12,0] =
[0.+0.j 1.+1.j 2.+2.j 3.+3.j 4.+0.j 5.+1.j 6.+2.j 7.+3.j 0.+0.j 1.+1.j
 2.+2.j 3.+3.j]

Output[0:12,0] =
[ 3.5       +0.j -0.95834839+0.j  0.        +0.j -0.32173021+0.j
  0.        +0.j -0.19440795+0.j  0.        +0.j -0.13984233+0.j
  0.        +0.j -0.10952898+0.j  0.        +0.j -0.09023946+0.j]

霓虹灯功能ne10_fft_c2r_1d_float32_neon调用为:

ne10_fft_c2r_1d_float32_neon( data_time_final[output_channel_number],BUFFER_BF_OUTPUT[output_channel_number],cfg_fft_r2c );

请参阅文档:https://github.com/projectNe10/Ne10/blob/master/inc/NE10_dsp.h

输出

3.500000000000000000
-0.958348393440246582
0.000000009662471712
-0.321730166673660278,0.000000001629814506
-0.194407939910888672
-0.000000014028046280
-0.139842316508293152
0.000000007217749953
-0.109529010951519012
0.000000007741618901
-0.090239435434341431

但是,对于“现实生活”数据,输出存在显着差异:

After IFFT Python: [-5.75256348e-08+0.j -1.14624023e-07+0.j -2.39105225e-07+0.j  -3.28216553e-07+0.j]
After IFFT C: [-5.58793545e-08 -1.11758709e-07 -2.42143869e-07 -3.29688191e-07]

您能解释一下为什么相对于1e-6的相对误差而言结果不同而又不同吗

解决方法

通常,数值舍入误差随FFT变换大小而增加。同样,不同的FFT实现可能具有不同的舍入误差。例如。有些使用递归公式可以减少内存成本,但会产生较大的舍入错误。

关于FFTW的此页面是各种FFT实现的准确性比较: http://www.fftw.org/accuracy/Pentium4-3.60GHz-icc/
对于基于32位浮点数据的4096大小FFT,某些实现的相对RMS误差确实比1e-6差。另请参见their commentary,了解FFT的准确性。