es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo interpretar el resultado R2C de cuFFT

Estoy en el proceso de acelerar algún código de análisis de datos con GPU y actualmente estoy haciendo algunos perfiles y comparaciones entre la biblioteca numpy.fft y cuFFT (utilizando el envoltorio skcuda.fft).

Estoy seguro de que solo estoy pasando por alto algo obvio sobre la implementación de FFT en cuFFT, pero estoy luchando por encontrar qué es en la documentación de cuFFT.

Para configurar el problema, creo 500 ms de datos muestreados a 100 MS/s con algunos componentes espectrales. Luego, declaro los arrays de GPU, el plan cufft (R2C) y ejecuto la fft con un subconjunto de los datos. Finalmente, hago una comparación con numpy.fft.rfft:

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

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

nPtsFFT = int(2**13)

dDev = gp.GPUArray(nPtsFFT, np.float64)
dDev.set(datos[: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/frecuencia)
hfftRes = np.fft.rfft(datos[:nPtsFFT])

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

Naive comparison of cuFFT and npfft

Esto me recordó a la salida de scipy.fftpack.rfft, así que al verificar la documentación allí, encontré la intercalación de las partes Re e Im. Por lo tanto, si modifico la trama a:

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()

Comparison compensating for interleave Re and Im output

Ahora obtengo lo que espero, pero solo hasta 25 MHz, cuando debería poder obtener datos de hasta 50 MHz dada la frecuencia de muestreo.

¿Hay alguna manera de extraer los datos hasta la frecuencia de Nyquist de esta transformación?

Tags:  ,

Answer

  1. Avatar for davy.ai

    Parece que la discrepancia entre los resultados de numpy.fft y cuFFT (a través de scikit-cuda) puede deberse a la intercalación de las partes real e imaginaria en la salida de cuFFT. Esto se puede compensar en la representación gráfica tomando cada otro punto y combinándolos como la suma de las partes real e imaginaria multiplicadas por una unidad compleja. Sin embargo, se observa que esta solución solo funciona hasta los 25 MHz, que es la mitad de la frecuencia de Nyquist dada la tasa de muestreo utilizada en el código de ejemplo.

    Para extraer los datos hasta la frecuencia de Nyquist de esta transformación, puede ser necesario tener en cuenta las restricciones específicas de los datos y el análisis deseado. Puede ser útil consultar la documentación de cuFFT para comprender mejor el comportamiento y las limitaciones específicas de la biblioteca. Además, experimentar con diferentes configuraciones y enfoques de la FFT puede proporcionar ideas para optimizar el análisis para el caso de uso específico.

Comments are closed.