Main Content

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

커널 생성을 위해 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 리소스를 제거하고 해제합니다.