FFT Example
This example shows how a two-dimensional Fourier transform can be used on an optical mask to compute its diffraction pattern. Create a logical array that defines an optical mask with a small, circular aperture.
n = 2^10; % size of mask M = zeros(n); I = 1:n; x = I-n/2; % mask x-coordinates y = n/2-I; % mask y-coordinates [X,Y] = meshgrid(x,y); % create 2-D mask grid R = 10; % aperture radius A = (X.^2 + Y.^2 <= R^2); % circular aperture of radius R M(A) = 1; % set mask elements inside aperture to 1 figure imagesc(M) % plot mask axis image DP = fftshift(fft2(M)); imagesc(abs(DP)) axis image
Prepare myFFT
for Kernel Creation
Create an entry-point function myFFT
that computes the 2-D Fourier
transform of the mask by using the fft2
function. Use the fftshift
function to rearrange the output so that the zero-frequency component
is at the center. To map this function to a GPU kernel, place the coder.gpu.kernelfun
pragma within the
function.
function [DP] = myFFT(M)
coder.gpu.kernelfun();
DP = fftshift(fft2(M));
Generated CUDA Code
When you generate CUDA® code, GPU Coder™ creates function calls (cufftEnsureInitialization
) to
initialize the cuFFT library, perform FFT operations, and release hardware resources that
the cuFFT library uses. A snippet of the generated CUDA code is:
void myFFT(myFFTStackData *SD, const real_T M[1048576], creal_T DP[1048576]) { ... cudaMemcpy((void *)gpu_M, (void *)M, 8388608ULL, cudaMemcpyHostToDevice); myFFT_kernel1<<<dim3(2048U, 1U, 1U), dim3(512U, 1U, 1U)>>>(gpu_M, gpu_b); cufftEnsureInitialization(1024, CUFFT_D2Z, 1024, 1024); cufftExecD2Z(*cufftGlobalHandlePtr, (cufftDoubleReal *)&gpu_b[0], (cufftDoubleComplex *)&gpu_y1[0]); ... myFFT_kernel2<<<dim3(2048U, 1U, 1U), dim3(512U, 1U, 1U)>>>(gpu_y1, gpu_y); cufftEnsureInitialization(1024, CUFFT_Z2Z, 1024, 1024); cufftExecZ2Z(*cufftGlobalHandlePtr, (cufftDoubleComplex *)&gpu_y[0], (cufftDoubleComplex *)&gpu_DP[0], CUFFT_FORWARD); ... cufftEnsureDestruction(); ... }
The first cudaMemcpy
function call transfers the 1024x1024
double-valued input M
to the GPU memory. The
myFFT_kernel1
kernel performs pre-processing of the input data before
the cuFFT library calls. The two-dimensional Fourier transform call fft2
is equivalent to computing fft(fft(M).').'
. Because batched transforms
generally have higher performance compared to single
transforms, GPU Coder has two 1-D cuFFT calls cufftExecD2Z
to compute the
double-precision real-to-complex forward transform of the input M
followed by cufftExecZ2Z
to perform the double-precision
complex-to-complex transform of the result. The cufftEnsureDestruction()
call destroys and frees GPU resources associated with the cuFFT library call.