【发布时间】: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,istride和ostride可能会是nTx*nRx,idist和odist可能等于 1,batch将是nTx*nRx。该计划将被执行nSamp次,使用int(data_t_gpu.gpudata)+i*nTx*nRx*nChirp作为输入和输出。 -
谢谢罗伯特和弗朗西斯。我将尝试列出的建议并返回。再次感谢。
-
发表我的尝试,我不得不得出结论: