Пример БПФ

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

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

Когда вы генерируете код 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 вызовом библиотеки.