Этот пример показывает, как двумерное преобразование Фурье может использоваться на оптической маске, чтобы вычислить ее дифракционный шаблон. Создайте логический массив, который задает оптическую маску с маленькой, круговой апертурой.
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
myFFT
к созданию ядраСоздайте функцию точки входа myFFT
, который вычисляет 2D преобразование Фурье маски при помощи функции fft2
. Используйте функцию fftshift
, чтобы перестроить вывод так, чтобы нулевая частотная составляющая находилась в центре. Чтобы сопоставить эту функцию с ядром графического процессора, поместите прагму coder.gpu.kernelfun
в функции.
function [DP] = myFFT(M)
coder.gpu.kernelfun();
DP = fftshift(fft2(M));
Когда вы генерируете код CUDA®, GPU Coder™ создает вызовы функции (cufftEnsureInitialization
), чтобы инициализировать cuFFT библиотеку, выполнить операции FFT и выпустить аппаратные ресурсы, которые использует cuFFT библиотека. Отрывок сгенерированного кода CUDA:
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(); ... }
Первый вызов функции cudaMemcpy
передает 1024x1024 вход M
с двойным знаком к памяти графического процессора. Ядро myFFT_kernel1
выполняет предварительную обработку входных данных перед cuFFT вызовами библиотеки. Двумерный вызов преобразования Фурье fft2
эквивалентен вычислению fft(fft(M).').'
. Поскольку пакетные преобразования обычно имеют более высокую производительность по сравнению с одним преобразованиями, GPU Coder имеет два 1D вызова cuFFT cufftExecD2Z
, чтобы вычислить действительное к комплексу прямое преобразование с двойной точностью входа M
, сопровождаемого cufftExecZ2Z
, чтобы выполнить преобразование от комплекса к комплексу с двойной точностью результата. Вызов cufftEnsureDestruction()
уничтожает и освобождает все ресурсы графического процессора, сопоставленные с cuFFT вызовом библиотеки.