주요 콘텐츠

FFT 예제

이 예제에서는 광학 마스크에 대한 회절 패턴을 계산하기 위해 2차원 푸리에 변환을 어떻게 사용하는지 보여줍니다. 원형의 작은 조리개가 장착된 광학 마스크를 정의하는 논리형 배열을 만듭니다.

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

The left image is the original optical mask. The right image is the result from applying the Fourier transform to the mask.

커널 생성을 위해 myFFT 준비하기

fft2 함수를 사용하여 마스크의 2차원 푸리에 변환을 계산하는 진입점 함수 myFFT를 만듭니다. fftshift 함수를 사용하여 영주파수 성분이 중앙에 오도록 출력값을 재배열합니다. 이 함수 내에 coder.gpu.kernelfun 프라그마를 추가하여 함수를 GPU 커널에 매핑합니다.

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 double형 값을 갖는 입력값 M을 GPU 메모리로 전송합니다. myFFT_kernel1 커널은 cuFFT 라이브러리를 호출하기 전에 입력 데이터의 전처리를 수행합니다. 2차원 푸리에 변환 호출 fft2fft(fft(M).').'을 계산하는 것과 동일합니다. 일괄 처리 변환이 일반적으로 단일 변환에 비해 성능이 더 높기 때문에, GPU Coder에는 입력값 M에 대한 배정밀도 실수-복소수 순방향 변환 계산을 위한 두 개의 1차원 cuFFT 호출 cufftExecD2Z이 있으며, 그 결과에 대해 배정밀도 복소수-복소수 변환을 수행하기 위한 cufftExecZ2Z가 있습니다. cufftEnsureDestruction() 호출은 cuFFT 라이브러리 호출과 관련된 GPU 리소스를 제거하고 해제합니다.