Main Content

GPU 코드 생성: 망델브로 집합

이 예제에서는 GPU Coder™를 사용하여 간단한 MATLAB® 함수에서 CUDA® 코드를 생성하는 방법을 보여줍니다. 표준 MATLAB 명령을 사용하여 망델브로 집합을 구현하는 경우 이는 진입점 함수 역할을 합니다. 이 예제에서는 codegen 명령을 사용하여 GPU에서 실행되는 MEX 함수를 생성합니다. MEX 함수를 실행하여 런타임 오류가 있는지 검사할 수 있습니다.

타사 선행 조건

필수

이 예제는 CUDA MEX를 생성하며, 다음과 같은 타사 요구 사항이 있습니다.

  • CUDA 지원 NVIDIA® GPU 및 호환되는 드라이버.

선택 사항

정적, 동적 라이브러리 또는 실행 파일과 같은 비 MEX 빌드의 경우, 이 예제에는 다음과 같은 추가 요구 사항이 있습니다.

GPU 환경 확인하기

coder.checkGpuInstall 함수를 사용하여 이 예제를 실행하는 데 필요한 컴파일러와 라이브러리가 올바르게 설치되었는지 확인합니다.

envCfg = coder.gpuEnvConfig('host');
envCfg.BasicCodegen = 1;
envCfg.Quiet = 1;
coder.checkGpuInstall(envCfg);

망델브로 집합

망델브로 집합은 복소 평면에서 다음과 같이 정의된 궤적이 있는 값 z0으로 구성된 영역입니다.

zk+1=zk2+z0,k=0,1,...

궤적은 k에서 유계를 유지합니다. 망델브로 집합의 전체적인 기하학적 구조는 아래 그림에 나와 있습니다. 아래 뷰는 집합 경계 바로 바깥쪽의 섬세한 구조를 보여줄 만큼의 해상도를 갖고 있지는 않습니다.

입력 영역 정의하기

메인 카디오이드(심장 모양의 곡선)와 그 왼쪽에 있는 p/q 전구 사이의 골에서 망델브로 집합의 크게 확대된 부분을 지정하는 경계 집합을 선택합니다. 이 두 경계 사이에 Re{x}Im{y}1000x1000 그리드가 생성됩니다. 그런 다음 각 그리드 위치에서 망델브로 알고리즘을 반복합니다. 500회의 반복 횟수는 영상을 전체 해상도로 렌더링하는 데 충분합니다.

maxIterations = 500;
gridSize = 1000;
xlim = [-0.748766713922161, -0.748766707771757];
ylim = [ 0.123640844894862,  0.123640851045266];

x = linspace( xlim(1), xlim(2), gridSize );
y = linspace( ylim(1), ylim(2), gridSize );
[xGrid,yGrid] = meshgrid( x, y );

망델브로 진입점 함수

mandelbrot_count.m 진입점 함수에는 Cleve Moler가 저술한 eBook Experiments with MATLAB에 제공된 코드를 기반으로 한 망델브로 집합의 벡터화된 구현이 포함되어 있습니다. %#codegen 지시문은 MATLAB에서 코드 생성 오류 검사를 활성화합니다. GPU Coder에서 coder.gpu.kernelfun 프라그마를 발견하면 이 함수 내의 모든 계산을 병렬화하려고 시도한 다음 이를 GPU에 매핑합니다.

type mandelbrot_count
function count = mandelbrot_count(maxIterations,xGrid,yGrid) %#codegen

% Copyright 2016-2024 The MathWorks, Inc. 

z0 = complex(xGrid, yGrid);
count = ones(size(z0));

% Map computation to GPU.
coder.gpu.kernelfun;

z = z0;
for n = 0:maxIterations
    z = z.*z + z0;
    inside = abs(z)<=2;
    count = count + inside;
end
count = log(count);

mandelbrot_count의 기능 테스트하기

이전에 생성한 xGrid, yGrid 값으로 mandelbrot_count 함수를 실행한 다음 결과를 플로팅합니다.

count = mandelbrot_count(maxIterations, xGrid, yGrid);

figure(2), imagesc( x, y, count );
colormap( [jet();flipud( jet() );0 0 0] );
title('Mandelbrot Set on MATLAB');
axis off

Figure contains an axes object. The axes object with title Mandelbrot Set on MATLAB contains an object of type image.

함수에 대한 CUDA MEX 생성하기

mandelbrot_count 함수에 대한 CUDA MEX를 생성하려면 GPU 코드 구성 객체를 만들고 codegen 명령을 실행합니다. CPU와 GPU의 아키텍처 차이로 인해 수치 검증이 항상 일치하지는 않습니다. 이 시나리오는 MATLAB 코드에서 single 데이터형을 사용하고 이러한 single 데이터형 값에 대해 누적 연산을 수행하는 경우에 해당합니다. 이 망델브로 예제에서는 double 데이터형도 수치 오차를 일으킵니다. 이러한 불일치가 발생하는 한 가지 이유는 GPU 부동소수점 유닛이 부동소수점 FMAD(단일 곱셈-누산) 명령어를 사용하는 반면 CPU는 이러한 명령어를 사용하지 않기 때문입니다. nvcc 컴파일러에 전달되는 fmad=false 옵션은 이 FMAD 최적화를 끕니다.

cfg = coder.gpuConfig('mex');
cfg.GpuConfig.CompilerFlags = '--fmad=false';
codegen -config cfg -args {maxIterations,xGrid,yGrid} mandelbrot_count
Code generation successful: View report

MEX 함수 실행하기

MEX 함수를 생성한 후, 이 함수가 원래 MATLAB 진입점 함수와 동일한 기능을 갖는지 확인합니다. 생성된 mandelbrot_count_mex를 실행하고 결과를 플로팅합니다.

countGPU = mandelbrot_count_mex(maxIterations, xGrid, yGrid);

figure(2), imagesc( x, y, countGPU );
colormap( [jet();flipud( jet() );0 0 0] );
title('Mandelbrot Set on GPU');
axis off

Figure contains an axes object. The axes object with title Mandelbrot Set on GPU contains an object of type image.

참고 항목

함수

객체

관련 항목