このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
GPU コード生成: マンデルブロ集合
この例では、GPU Coder™ を使用して簡単な MATLAB® 関数から CUDA® コードを生成する方法を説明します。標準の MATLAB コマンドを使用したマンデルブロ集合の実装は、エントリポイント関数として機能します。この例では、codegen
コマンドを使用して、GPU で実行される MEX 関数を生成します。この MEX 関数を実行して実行時エラーをチェックすることができます。
サードパーティの必要条件
必須
この例では、CUDA MEX を生成します。以下のサードパーティ要件が適用されます。
CUDA 対応 NVIDIA® GPU および互換性のあるドライバー。
オプション
スタティック ライブラリ、ダイナミック ライブラリ、または実行可能ファイルなどの MEX 以外のビルドについて、この例では以下の要件も適用されます。
NVIDIA Toolkit。
コンパイラおよびライブラリの環境変数。詳細については、サードパーティ ハードウェアと前提条件となる製品の設定を参照してください。
GPU 環境の検証
この例を実行するのに必要なコンパイラおよびライブラリが正しく設定されていることを検証するために、関数coder.checkGpuInstall
を使用します。
envCfg = coder.gpuEnvConfig('host');
envCfg.BasicCodegen = 1;
envCfg.Quiet = 1;
coder.checkGpuInstall(envCfg);
マンデルブロ集合
マンデルブロ集合とは、値 で構成された複素平面の領域であり、この値は
で定義された軌跡が のときに有限の範囲内にとどまるときの値です。マンデルブロ集合の全体的な幾何形状を図に示しています。この図には、集合の境界の外側周辺における詳しい構造を十分に示すための解像度がありません。
入力領域の定義
メインのカージオイドとその左側にある 球状部との谷間にある、マンデルブロ集合の大きく拡大された部分を指定する一連の範囲を選択します。これらの 2 つの範囲間に、 と の 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
_c
ount.m
には、電子書籍 Experiments with MATLAB (Cleve Moler 著) で提供されているコードに基づくマンデルブロ集合のベクトル化済みの実装が含まれています。%#codegen
命令は、MATLAB のコード生成エラー チェックをオンにします。GPU Coder は coder.gpu.kernelfun
プラグマを検出すると、この関数内のすべての計算を並列化し、その計算を GPU にマッピングしようとします。
type mandelbrot_count
function count = mandelbrot_count(maxIterations, xGrid, yGrid) %#codegen % Copyright 2016-2019 The MathWorks, Inc. z0 = xGrid + 1i*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
_c
ount
の機能のテスト
前に生成した xGrid 値と yGrid 値を指定して関数 mandelbrot
_c
ount
を実行し、その結果をプロットします。
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
関数の CUDA MEX の生成
関数 mandelbrot
_c
ount
の CUDA MEX を生成するには、GPU コード構成オブジェクトを作成し、codegen
コマンドを実行します。CPU と GPU ではアーキテクチャが異なるため、数値検証が常に一致するとは限りません。このシナリオは、single データ型を MATLAB コードで使用し、これらの single データ型の値に対して累積演算を実行する場合に当てはまります。このマンデルブロの例のように、double データ型であっても数値誤差の原因になり得ます。この不一致が発生する 1 つの原因は、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
_c
ount_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