簡體   English   中英

如何解釋 cuFFT R2C 結果

[英]How to interpret cuFFT R2C result

我正在使用 GPU 加速一些數據分析代碼,目前正在 numpy.fft 庫和 cuFFT(使用 skcuda.fft 包裝器)之間進行一些分析和比較。

我確定我只是錯過了一些關於 cuFFT 中 FFT 實現的明顯內容,但我很難在 cuFFT 文檔中找到它。

為了解決這個問題,我創建了 500 ms 的數據,以 100 MS/s 的速度采樣,並帶有一些光譜分量。 然后,我聲明 GPU arrays、袖帶計划 (R2C) 並使用數據子集運行 fft。 最后和numpy.fft.rfft對比一下:

time = np.linspace(0, 500E-3, int(50E6))
freq = 100E6

data = np.sin(2*np.pi*time*1E6)
data += np.sin(2*np.pi*time*2E6 + 0.5)
data += np.sin(2*np.pi*time*3E6 - 0.1)
data += np.sin(2*np.pi*time*4E6 - 0.9)
data += np.sin(2*np.pi*time*1E6 - 1.9)
data += np.sin(2*np.pi*time*15E6 - 2.1)
data += np.sin(2*np.pi*time*20E6 - 0.3)
data += np.sin(2*np.pi*time*25E6 - 0.3)

nPtsFFT = int(2**13)

dDev = gp.GPUArray(nPtsFFT, np.float64)
dDev.set(data[:nPtsFFT])

rDev = gp.GPUArray(int(nPtsFFT/2+1), np.float64)

plan = cufft.Plan(nPtsFFT, np.float64, np.complex128)
cufft.fft(dDev, rDev, plan)
rHost = rDev.get()

freqs = np.fft.rfftfreq(nPtsFFT, 1/freq)
hfftRes = np.fft.rfft(data[:nPtsFFT])

plt.loglog(freqs, np.abs(hfftRes), label='npfft')
plt.loglog(freqs, np.abs(rHost), label='cufft')
plt.legend()
plt.show()

我天真地假設這些將大致相等,但我發現袖帶峰都發生了偏移,並且每隔一個點都低於預期。

cuFFT 和 npfft 的簡單比較

這讓我想起了 scipy.fftpack.rfft 的 output,所以檢查那里的文檔我發現了 Re 和 Im 部分的交錯。 因此,如果我將繪圖修改為:

plt.loglog(freqs, np.abs(hfftRes), label='npfft')
plt.loglog(freqs[:-1:2]/2, np.abs(rHost[:-1:2] + 1j*rHost[1::2]), label='cufft')
plt.legend()
plt.show()

我現在得到了我期望的結果,但最高只有 25 MHz,而在給定采樣率的情況下,我應該能夠獲得高達 50 MHz 的數據。

比較補償交錯 Re 和 Im 輸出

有沒有辦法從這個變換中提取高達奈奎斯特頻率的數據?

由於 R2C 接口產生復數輸出,因此您必須提供np.complex128類型的數組來獲取整個int(nPtsFFT/2+1)復數值,而不僅僅是int(nPtsFFT/2+1)浮點值(對應於數據量的一半)。

這可以通過如下更改rDev定義來完成(並保持其他所有內容相同):

rDev = gp.GPUArray(int(nPtsFFT/2+1), np.complex128)

plan = cufft.Plan(nPtsFFT, np.float64, np.complex128)
cufft.fft(dDev, rDev, plan)
rHost = rDev.get()

freqs = np.fft.rfftfreq(nPtsFFT, 1/freq)
hfftRes = np.fft.rfft(data[:nPtsFFT])

plt.loglog(freqs, np.abs(hfftRes), label='npfft')
plt.loglog(freqs, np.abs(rHost), label='cufft')
plt.legend()
plt.show()

結果應該是 go 一直到預期的 50MHz 奈奎斯特頻率,尖峰與參考np.fft.rfft實現很好地對齊。

我還沒有找到對cufft的解釋,但是我可以使用cupyx.scipy.fft.rfft獲得我想要的行為,如果其他人發現同樣的問題,這可能會很有用。

deviceData = cp.array(data, dtype = np.float64)
fftPlan = cpfftPack.get_fft_plan(deviceData[:nPtsFFT], (nPtsFFT,),
                                 value_type = 'R2C')
dfft = cpfft.rfft(deviceData[:nPtsFFT], plan = fftPlan)
h_dfft = dfft.get()
hfft = npfft.rfft(data[:nPtsFFT])

plt.loglog(freqs, np.abs(hfft), label='npfft')
plt.loglog(freqs, np.abs(h_dfft), label='cupyx fft')
plt.legend()
plt.show()

在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM