【问题标题】:How to schedule multiple 1d FFTs using Scikit-cuda FFT?如何使用 Scikit-cuda FFT 调度多个 1d FFT?
【发布时间】:2019-09-15 02:47:07
【问题描述】:

我希望使用 CUDA 并行化多个 1d FFT。我正在使用 CUDA 6.1 开发 GTX 1050Ti。

例如,在我附加的代码中,我有一个 3d 输入数组“数据”,我想在这个数组的第二维上进行 1d FFT。当然,目的是将执行时间加快一个数量级。

我可以使用 Python 的 scikit-cuda 的 cufft 包运行一批 1 1d FFT,结果与 NumPy 的 FFT 匹配。当我达到真正的批量大小时,问题就来了。在那里,我无法将 NumPy 的 FFT 输出(正确的输出)与 cufft 的输出(我认为这是不正确的)相匹配。在附加的代码中,参数“singleFFT”控制我们是安排一批还是一批。非常感谢您帮助纠正输出 FFT 并进一步加快执行速度(如果可能)。

import numpy as np
from time import process_time
from skcuda import cufft as cf
import pycuda.autoinit
from pycuda import gpuarray


# params
nSamp = 512
nTx = 16
nRx = 16
nChirp = 256
NX = nChirp
# Uncomment the following line to generate same data always
# np.random.seed(seed=1)
data = (np.random.randn(nSamp,nChirp,nTx,nRx) + 1j*np.random.randn(nSamp,nChirp,nTx,nRx)).astype(np.complex64)
data = data.reshape(nSamp,-1,nTx*nRx)
dataShp0 = np.int32(data.shape[0])
dataShp2 = np.int32(data.shape[2])
idx1 = 0
idx2 = 0
idx3 = 0
singleFFT = 0
if (1 == singleFFT):
    data_t      = data[0,:,0]
    fftAxis = 0
    BATCH = np.int32(1)
else:
    data_t      = data
    fftAxis = 1
    BATCH = np.int32(nSamp*nTx*nRx)
# calculate and time NumPy FFT
t1 = process_time()
dataFft     = np.fft.fft(data_t, axis=fftAxis)
t2 = process_time()
print('\nCPU NumPy time is: ',t2-t1)

data_o_gpu  = gpuarray.empty((BATCH*NX),dtype=np.complex64)
# calculate and time GPU FFT
data_t = data_t.reshape((BATCH*NX))
t1 = process_time()
# transfer input data to Device
data_t_gpu  = gpuarray.to_gpu(data_t)
# Make FFT plan
plan = cf.cufftPlan1d(NX, cf.CUFFT_C2C, BATCH)
# Execute FFT plan
res = cf.cufftExecC2C(plan, int(data_t_gpu.gpudata), int(data_o_gpu.gpudata), cf.CUFFT_FORWARD)

dataFft_gpu = data_o_gpu.get()
t2 = process_time()
if (0 == singleFFT):
    dataFft_gpu = dataFft_gpu.reshape((nSamp,-1,nTx*nRx))
print('\nGPU time is: ',t2-t1)
print(np.allclose(dataFft,dataFft_gpu,atol=1e-6))

代码中的最后一行将 NumPy 的 FFT 与 cuFFT 的结果相匹配。可以看出singleFFT=1,结果为True,而singleFFT=0(即很多1d FFT的batch),结果为False。

【问题讨论】:

  • here 是使用 cupy 的示例。
  • 欢迎来到 Stackoverflow!由于 DFT 不在最后一个维度上执行,因此要应用 DFT 的实际一维数组可能是交错的。你可以试试cufftPlanMany(),因为它支持批量输入和跨步数据布局。 rank 将是 1,istrideostride 可能会是 nTx*nRxidistodist 可能等于 1,batch 将是 nTx*nRx。该计划将被执行nSamp 次,使用int(data_t_gpu.gpudata)+i*nTx*nRx*nChirp 作为输入和输出。
  • 谢谢罗伯特和弗朗西斯。我将尝试列出的建议并返回。再次感谢。
  • 发表我的尝试,我不得不得出结论:

标签: python numpy gpgpu cufft


【解决方案1】:

发布我的尝试,我想得出以下结论:

  • 使用 skcuda 的 cufft 库有点棘手,在开发过程中,要获得正确的 FFT 输出可能需要很长时间。我还注意到 NumPy 的 FFT 和 cufft 的 FFT(来自 skcuda)之间的执行时间没有数量级差异

  • 使用 CuPy 并以某种格式排列数据,使 FFT 维度布局在连续内存中,可以将 FFT 计算时间缩短一个数量级。就我而言,订单比 10 好一点!

  • 如果只想坚持基于 Py 的开发,使用 CuPy 进行 FFT 是一个不错的选择。此外,在编写 C GPU 内核时,从 C 到 Python 的往返是一个额外的开销,这可以通过 CuPy 非常方便地解决。尽管 CuPy 本身要求制定计划并在内部调用 FFT 执行引擎。

【讨论】:

    猜你喜欢
    • 2012-07-05
    • 2018-09-05
    • 1970-01-01
    • 2020-08-27
    • 1970-01-01
    • 1970-01-01
    • 2014-10-14
    • 1970-01-01
    • 2014-05-18
    相关资源
    最近更新 更多