В этом примере показано, как двумерное преобразование Фурье может использоваться на оптической маске, чтобы вычислить ее дифракционный шаблон. Создайте логический массив, который задает оптическую маску с маленькой, круговой апертурой.
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 вызовом библиотеки.