コマンド ライン インターフェイスを使用したコード生成
CUDA® カーネルを作成する最も簡単な方法は、coder.gpu.kernelfun
プラグマを "基本" MATLAB® 関数に配置することです。基本関数は、"最上位" 関数または "エントリポイント" 関数とも呼ばれます。GPU Coder™ は kernelfun
プラグマを検出すると、この関数内のすべての計算を並列化し、その計算を GPU にマッピングしようとします。
学習目標
このチュートリアルでは、次の方法を学びます。
kernelfun
プラグマを使用した CUDA コード生成のための MATLAB コードの準備。GPU Coder プロジェクトの作成と設定。
関数入力のプロパティの定義。
コード生成の準備状態と実行時の問題のチェック。
コード生成のプロパティの指定。
codegen
コマンドを使用した CUDA コードの生成。
チュートリアルの前提条件
このチュートリアルには、次の製品が必要です。
MATLAB
MATLAB Coder™
GPU Coder
C コンパイラ
CUDA 対応 NVIDIA® GPU
CUDA Toolkit およびドライバー
コンパイラおよびライブラリの環境変数。詳細については、環境変数を参照してください。
例:マンデルブロ集合
説明
マンデルブロ集合とは、下記の方程式で定義された軌跡が k→∞ のときに有限の範囲内にとどまる値 z0 で構成された複素平面の領域です。
マンデルブロ集合の全体的な幾何形状を図に示しています。この図には、集合の境界の外側周辺における詳しい構造を十分に示すための解像度がありません。拡大率を上げていくと、マンデルブロ集合の詳細な境界が示され、そこでは徐々に細かくなりながら細部が繰り返されていることがわかります。
アルゴリズム
このチュートリアルでは、メインのカージオイドとその左側にある p/q 球状部との谷間にある、マンデルブロ集合の大きく拡大された部分を指定する一連の範囲を選択します。これらの 2 つの範囲間に、実数部 (x) と虚数部 (y) の 1000 x 1000 のグリッドを作成します。次に、マンデルブロ アルゴリズムを各グリッド位置で反復します。500 回の反復回数で、完全な解像度のイメージがレンダリングされます。
maxIterations = 500; gridSize = 1000; xlim = [-0.748766713922161,-0.748766707771757]; ylim = [0.123640844894862,0.123640851045266];
このチュートリアルでは、CPU で実行される標準の MATLAB コマンドを使ったマンデルブロ集合の実装を使用します。この計算はすべての場所が同時に更新されるようにベクトル化されています。
チュートリアル ファイル
次のコード行を使用して mandelbrot_count.m
という MATLAB スクリプトを作成します。このコードは、マンデルブロ集合のベースライン ベクトル化済みの MATLAB 実装です。このチュートリアルでは後ほど、コード生成に適するようにこのファイルを変更します。
function count = mandelbrot_count(maxIterations, xGrid, yGrid) % mandelbrot computation z0 = xGrid + 1i*yGrid; count = ones(size(z0)); z = z0; for n = 0:maxIterations z = z.*z + z0; inside = abs(z)<=2; count = count + inside; end count = log(count);
次のコード行を使用して mandelbrot_test.m
という MATLAB スクリプトを作成します。このスクリプトは、xlim
と ylim
で指定した範囲間に実数部 (x) と虚数部 (y) の 1000 x 1000 のグリッドを生成します。また、関数 mandelbrot_count
を呼び出して、結果のマンデルブロ集合をプロットします。
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 computation in MATLAB count = mandelbrot_count(maxIterations, xGrid, yGrid); % Show figure(1) imagesc( x, y, count ); colormap([jet();flipud( jet() );0 0 0]); axis off title('Mandelbrot set with MATLAB');
元の MATLAB コードの実行
マンデルブロの例の実行
MATLAB バージョンのマンデルブロ集合アルゴリズムをコード生成に適したものにする前に、元のコードの機能をテストできます。
MATLAB の現在の作業フォルダーを、前の手順で作成した 2 つのファイルが含まれた場所に変更します。GPU Coder はこのフォルダーに生成コード配置し、このフォルダーに対する完全なアクセス権がない場合は現在の作業フォルダーを変更します。
MATLAB エディターで
mandelbrot_test
スクリプトを開きます。実行ボタン
をクリックするか、MATLAB コマンド ウィンドウに
mandelbrot_test
を入力して、テスト スクリプトを実行します。テスト スクリプトが実行され、変数
xlim
およびylim
により設定された境界内のマンデルブロの幾何形状が表示されます。
コード生成に適した MATLAB コードの作成
MATLAB コードをコード生成に適したものにするプロセスを始める前に、ファイル mandelbrot_count.m
を使用します。
MATLAB の現在のフォルダーを、このチュートリアル用のファイルが含まれた作業フォルダーに設定します。
MATLAB エディターで、
mandelbrot_count.m
を開きます。ファイルが MATLAB エディターで開きます。MATLAB エディターの右上隅にあるコード アナライザー メッセージ インジケーターは緑色になっています。アナライザーは、コード内にエラー、警告、および改善機会を検出しませんでした。MATLAB のコード生成エラー チェックをオンにします。関数宣言の後ろに
%#codegen
命令を追加します。function count = mandelbrot_count(maxIterations, xGrid, yGrid) %#codegen
コード アナライザー メッセージ インジケーターは緑色のままです。これはコード生成の問題が検出されていないことを示します。
関数
mandelbrot_count
を CUDA カーネルにマッピングするには、元の MATLAB コードを変更し、for
ループ本体の外にcoder.gpu.kernelfun
プラグマを配置します。function count = mandelbrot_count(maxIterations, xGrid, yGrid) %#codegen % mandelbrot computation z0 = xGrid + 1i*yGrid; count = ones(size(z0)); % Add Kernelfun pragma to trigger kernel creation coder.gpu.kernelfun; z = z0; for n = 0:maxIterations z = z.*z + z0; inside = abs(z)<=2; count = count + inside; end count = log(count);
coder.gpu.kernelfun
プラグマの使用時は、GPU Coder は関数mandelbrot_count
の計算を GPU にマッピングしようとします。ファイルを保存します。コマンド ライン インターフェイスを使用してコードをコンパイルする準備が整いました。
コマンド ラインからのコード生成
GPU Coder アプリを使用する代わりに、codegen
コマンドを使用して、MATLAB 関数を CUDA と互換性のあるスタティック ライブラリ、ダイナミック ライブラリ、実行可能ファイル、または MEX 関数に変換できます。
入力の型を定義
コンパイル時に、GPU Coder はエントリポイント関数のすべての入力についてデータ型を把握していなければなりません。そのため、エントリポイント関数に入力がある場合は、関数 codegen
が含まれたファイルのコンパイル時にその入力のデータ型を指定する必要があります。
入力を生成してから、関数 codegen
に -args
オプションを使用することで、GPU Coder で入力パラメーターのクラス、サイズ、および実数/複素数を特定できるようになります。関数 mandelbrot_count
の入力を生成するには、次のコマンドを使用します。
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 );
または、関数 coder.typeof
を使用して、入力データを生成せずに、エントリポイント関数の入力のサイズ、型、および実数/複素数を指定できます。
ARGS = cell(1,1); ARGS{1} = cell(3,1); ARGS{1}{1} = coder.typeof(0); ARGS{1}{2} = coder.typeof(0,[1000 1000]); ARGS{1}{3} = coder.typeof(0,[1000 1000]);
ビルド構成
出力ファイル名、場所、タイプなどのビルド設定を構成するには、コーダー構成オブジェクトを作成しなければなりません。このオブジェクトを作成するには、関数 coder.gpuConfig
を使用します。たとえば、MEX 関数の生成時に codegen
で使用する coder.MexCodeConfig
コード生成オブジェクトを作成するには、以下を使用します。
cfg = coder.gpuConfig('mex');
その他の利用可能なオプションは次のとおりです。
cfg = coder.gpuConfig('lib');
、CUDA スタティック ライブラリの生成時にcodegen
で使用するコード生成構成オブジェクトを作成します。cfg = coder.gpuConfig('dll');
、CUDA ダイナミック ライブラリの生成時にcodegen
で使用するコード生成構成オブジェクトを作成します。cfg = coder.gpuConfig('exe');
、CUDA 実行可能ファイルの生成時にcodegen
で使用するコード生成構成オブジェクトを作成します。
詳細については、coder.gpuConfig
を参照してください。
各構成オブジェクトには、既定値に初期化された一連のパラメーターが伴います。ドット表記を使用して、一度に 1 つの構成オブジェクトのパラメーターの値を変更できます。次の構文を使用します。
configuration_object.property = value
次の同等のコマンド ラインを使用して、GPU Coder アプリを使用したコード生成と同じ設定を有効にすることができます。
cfg = coder.gpuConfig('mex'); cfg.GpuConfig.CompilerFlags = '--fmad=false'; cfg.GenerateReport = true;
cfg
構成オブジェクトには、MATLAB Coder と GPU Coder に共通する構成パラメーターと、GPU Coder 固有のパラメーターがあります。MATLAB コマンド ウィンドウに「cfg.GpuConfig
」と入力することで、cfg
構成オブジェクトで利用できるすべての GPU 固有のプロパティを確認できます。
>> cfg.GpuConfig ans = config with properties: Enabled: 1 MallocMode: 'discrete' KernelNamePrefix: '' EnableCUBLAS: 1 EnableCUSOLVER: 1 EnableCUFFT: 1 Benchmarking: 0 SafeBuild: 0 ComputeCapability: '3.5' CustomComputeCapability: '' CompilerFlags: '' StackLimitPerThread: 1024 MallocThreshold: 200 SelectCudaDevice: -1
--fmad=false
フラグは、nvcc
に渡すと、浮動小数点積和演算 (FMAD) 最適化を無効にするようにこのコンパイラに指示します。このオプションは、CPU と GPU のアーキテクチャの違いが原因で、生成コード上の数値の不一致を防ぐために設定します。詳細は、CPU と GPU の数値の差を参照してください。
MATLAB Coder と GPU Coder に共通する構成パラメーターの詳細については、coder.CodeConfig
クラスを参照してください。
ビルド スクリプト
前述した一連のコマンドを自動化するビルド スクリプト mandelbrot_codegen.m
を作成できます。
% GPU code generation for getting started example (mandelbrot_count.m) %% Create configuration object of class 'coder.MexCodeConfig'. cfg = coder.gpuConfig('mex'); cfg.GenerateReport = true; cfg.GpuConfig.CompilerFlags = '--fmad=false'; %% Define argument types for entry-point 'mandelbrot_count'. ARGS = cell(1,1); ARGS{1} = cell(3,1); ARGS{1}{1} = coder.typeof(0); ARGS{1}{2} = coder.typeof(0,[1000 1000]); ARGS{1}{3} = coder.typeof(0,[1000 1000]); %% Invoke GPU Coder. codegen -config cfg mandelbrot_count -args ARGS{1}
codegen
コマンドはファイル mandelbrot_count.m
を開き、MATLAB コードを CUDA コードに変換します。
-report
オプションは、MATLAB コードのデバッグに使用できるコード生成レポートを生成するようにcodegen
に指示します。-args
オプションは、入力パラメーター maxIterations、xGrid、および yGrid のクラス、サイズ、および実数/複素数を使用して、ファイルmandelbrot_count.m
をコンパイルするようにcodegen
に指示します。-config
オプションは、指定した構成オブジェクトをコード生成に使用するようにcodegen
に指示します。
コード生成に成功したら、MATLAB コマンド ウィンドウで [レポートの表示] をクリックすることで、結果のコード生成レポートを表示できます。
>> mandelbrot_codegen Code generation successful: View report
生成コードの正確性の検証
生成された MEX ファイルの正確性を検証するには、生成コードの正確性の検証を参照してください。