Main Content

他の開発環境への生成コードの移動

生成コードのファイルを、MATLAB® を含まないシステムや統合開発環境 (IDE) といった、他の開発環境に移動するには、コマンド ラインで関数 packNGo を使用するか、GPU Coder™ アプリで [パッケージ] オプションを使用します。ファイルは圧縮ファイルにパッケージ化され、標準の zip ユーティリティを使用して移動および解凍できます。

GPU Coder を使用して生成されたコードは、サードパーティのコンパイラとライブラリを利用して実行可能ファイルのビルドと実行を行うため、移動先の開発環境もその要件を満たしていなければなりません。詳細については、前提条件となる製品のインストール前提条件となる製品の設定を参照してください。

メモ

GPU Coder では、packNGo コマンドの 'minimalHeaders' オプションを false に設定する必要があります。この設定は、コードをビルドするのに必要な最低限のヘッダー ファイルではなく、zip ファイル内のインクルード パスで見つかったヘッダー ファイルをすべてインクルードするよう、ソフトウェアに指示します。たとえば、packNGo(buildInfo,'minimalHeaders',false) のようにします。

GPU Coder を使用した生成コードのパッケージ化

この例では、GPU Coder アプリの [パッケージ] オプションを使用して、移動用に生成コードを zip ファイルにパッケージ化する方法を説明します。この例では、ソーベル エッジ検出アプリケーションを使用してこの概念を説明します。既定では、GPU Coder は現在の作業フォルダーに zip ファイルを作成します。

必要条件

ソーベル エッジ検出エントリポイント関数

ソーベル エッジ検出アルゴリズムでは、グレースケール イメージに対する 2 次元の空間勾配演算が行われます。この演算は、エッジに相当する空間周波数の高い領域を強調します。

type sobelEdge.m
function [ magnitude ] = sobelEdge( Image )
%#codegen

%   Copyright 2017-2021 The MathWorks, Inc.


maskX = single([-1 0 1 ; -2 0 2; -1 0 1]);
maskY = single([-1 -2 -1 ; 0 0 0 ; 1 2 1]);

coder.gpu.kernelfun();



resX = conv2(Image, maskX, 'same');
resY = conv2(Image, maskY, 'same');

magnitude = sqrt(resX.^2 + resY.^2);
thresh = magnitude < 0.4;
magnitude(thresh) = 0;

end

ソーベル エッジ検出アルゴリズムは、2 つの直交フィルター カーネル (maskXmaskY) を使用して、入力イメージの水平方向勾配 (resX) と垂直方向勾配 (resY) を計算します。このアルゴリズムは、フィルター処理演算を実行した後、勾配の大きさを計算してしきい値を適用し、エッジと考えられるイメージの領域を見つけます。

テスト イメージに対するソーベル エッジ検出アルゴリズムの実行

ソーベル フィルター処理アルゴリズムは、グレースケール イメージに作用します。カラー イメージを、正規化された値をもつ (黒が 0.0、白が 1.0) 等価なグレースケール イメージに変換します。

im = imread('hello.jpg');
imGray = (0.2989 * double(im(:,:,1)) + 0.5870 * double(im(:,:,2)) +...
     0.1140 * double(im(:,:,3)))/255;
imSize = size(imGray);
figure();
image(im);
title('Test Image');

Figure contains an axes object. The axes object with title Test Image contains an object of type image.

writematrix コマンドを使用して、グレースケール イメージの行列を imputImage.csv ファイルに書き込みます。ソーベル エッジ検出アプリケーションが、この CSV ファイルを読み取ります。

writematrix(reshape(imGray,1,[]),'inputImage.csv');
imOut = sobelEdge(double(imGray));

エッジが検出されたイメージを表示するには、関数 repmat を使用して行列 imOut を再構築し、image コマンドに渡せるようにします。

figure();
image(repmat(imOut,[1 1 3]));
title('Edge Detected Image in MATLAB');

Figure contains an axes object. The axes object with title Edge Detected Image in MATLAB contains an object of type image.

sobelEdge.m 用カスタム main 関数の作成

この例では、カスタム メイン ファイル main_sobel.cu および関連するヘッダー ファイル main_sobel.h を使用します。このカスタム メイン ファイルは、inputImage.csv ファイルから入力イメージを読み取り、生成された sobelEdge.cu ファイルの関数 sobelEdge を呼び出し、エッジが検出されたイメージのデータを outputMag.csv ファイルに保存します。

GPU Coder アプリを使用した生成コードのパッケージ化

GPU Coder アプリを開きます。MATLAB ツールストリップの [アプリ] タブにある [コード生成] で、GPU Coder アプリ アイコンをクリックします。

[ソース ファイルの選択] ページで、エントリポイント関数の名前「sobelEdge.m」を入力します。[次へ] をクリックして [入力の型を定義] ページに進みます。

入力 Image が可変サイズ (上限が 1024) の double データ型であることを指定します。上限が 1024 の可変サイズを指定するには、:1024 を選択します。[次へ] をクリックして [実行時の問題の確認] ページに進みます。

実行時の問題をチェックします。[実行時の問題の確認] ダイアログ ボックスで、double の入力を使用して sobelEdge を呼び出すコードを入力します。たとえば、sobelEdge(ones(648,484)) のようにします。[問題の確認] をクリックします。実行時の問題を確認するため、アプリによって MEX 関数が生成され、実行されます。アプリは sobelEdge の問題を検出しません。[次へ] をクリックして [コードの生成] ページに進みます。

[生成] ダイアログ ボックスで、[ビルド タイプ] を [実行可能ファイル] に設定します。ソース コード、スタティック ライブラリ、またはダイナミック ライブラリのターゲット用に生成されたコードをパッケージ化することもできます。MEX ターゲット用に生成されたコードをパッケージ化することはできません。[詳細設定] をクリックします。

[生成されたファイルのカスタム C コード] の [カスタム コード] タブで、[追加ソース ファイル] を main_sobel.cu に設定します。[閉じる] をクリックして [コードの生成] ページに進みます。

[生成] をクリックします。[次へ] をクリックして [ワークフローの完了] ページに進みます。[ワークフローの完了] ページで、[パッケージ] をクリックします。

[パッケージ] ダイアログ ボックスで、パッケージ ファイル名とパッケージ化のタイプを指定します。既定では、アプリはプロジェクト名からパッケージ ファイル名を導出します。アプリは、現在の作業フォルダーにファイルを保存します。既定では、アプリは生成されたファイルを単一でサブフォルダーのないフォルダーとしてパッケージ化します。この例の場合、既定の値を使用し、[保存] をクリックします。

この zip ファイルには、移動に必要な CUDA C++ コードとヘッダー ファイルが格納されています。以下のものは含まれません。

  • コンパイル フラグ

  • 定義

  • makefile

  • メイン ファイルの例 (main 関数の例の生成とコンパイルを行うようにコード生成を設定した場合を除く)

作業フォルダー内の sobelEdge_pkg.zip の内容を検査し、移動先のシステムに移動する準備が整っているか確認します。使用する zip ツールによっては、解凍せずにファイルを開いて内容を検査できます。これで、得られた zip ファイルを目的の開発環境に移動して解凍できるようになりました。

コマンド ラインでの生成コードのパッケージ化

関数 sobelEdge 用の CUDA 実行可能ファイルを生成するには、GPU コード構成オブジェクトを作成して codegen コマンドを実行します。

cfg = coder.gpuConfig('exe');
cfg.GenerateReport = true;
cfg.CustomSource = 'main_sobel.cu';
inputArgs = {coder.typeof(0,[1024 1024],[1 1])};
codegen -config cfg sobelEdge -args inputArgs
Code generation successful: View report

生成コードを zip ファイルにパッケージ化するには、BuildInfo オブジェクトを読み込みます。BuildInfo オブジェクトには、生成コードをコンパイルしてリンクするのに必要な情報 (すべてのソースとインクルード ファイルの一覧、およびそれらのパス) が格納されています。

buildInfoFile = fullfile(pwd,'codegen','exe','sobelEdge', ...
    'buildInfo.mat');
load(buildInfoFile);

関数 packNGo を使用して、zip ファイルを作成します。

packNGo(buildInfo,'packType','flat','nestedZipFiles',true,...
    'minimalHeaders',false,'includeReport',false);

関数 packNGo は、現在の作業フォルダーに sobelEdge.zip ファイルを作成します。この zip ファイルには、移動に必要な CUDA C++ コードとヘッダー ファイルが格納されています。以下のものは含まれません。

  • コンパイル フラグ

  • 定義

  • makefile

  • メイン ファイルの例 (main 関数の例の生成とコンパイルを行うようにコード生成を設定した場合を除く)

作業フォルダー内の sobelEdge.zip の内容を検査し、移動先のシステムに移動する準備が整っているか確認します。使用する zip ツールによっては、解凍せずにファイルを開いて内容を検査できます。これで、得られた zip ファイルを目的の開発環境に移動して解凍できるようになりました。

スタンドアロン コードの実行

生成されたスタンドアロン実行可能ファイルを実行すると、出力 magnitudeData が計算されてコンマ区切りのファイルに書き込まれます。この出力を MATLAB に読み戻し、関数 image を使用して、エッジが検出されたイメージを可視化します。

if ispc
    system('sobelEdge.exe');
else
    system('./sobelEdge');
end

imOutGPU = reshape(readmatrix('outputMag.csv'),imSize);
edgeImg = repmat(imOutGPU,[1 1 3]);
figure();
image(edgeImg);
title('Edge Detected Image on the GPU');

Figure contains an axes object. The axes object with title Edge Detected Image on the GPU contains an object of type image.

packNGo のオプションの指定

関数 packNGo のオプションを指定できます。

目的Specify

ファイルのパッケージ化の構造を階層構造に変更する。

packNGo(buildInfo,'packType','hierarchical');

ファイルのパッケージ化の構造を階層構造に変更し、プライマリ zip ファイルの名前を変更する。

packNGo(buildInfo,'packType','hierarchical',...
'fileName','zippedsrcs');

コードをビルドするのに必要な最低限のヘッダー ファイルではなく、zip ファイル内のインクルード パスで見つかったヘッダー ファイルをすべてインクルードする。

GPU Coder では、このオプションを false に設定しなければなりません。

packNGo(buildInfo,'minimalHeaders',false);

解析エラーと不足しているファイルの警告を生成する。

packNGo(buildInfo,'ignoreParseError', true,...
'ignoreFileMissing',true);

詳細については、packNGo を参照してください。

zip ファイルの構造の選択

ファイルを生成してパッケージ化する前に、サブフォルダーがないフォルダー構造にするか、階層的なフォルダー構造にするか決定してください。既定では、関数 packNGo はファイルを単一でサブフォルダーのない構造としてパッケージ化します。通常はこの方法が最も簡潔で最適な選択肢です。

条件使用
生成された makefile を使用しない IDE にファイルを移動するつもりである。または、必要な静的ファイルの相対位置を利用しないコードである 単一でサブフォルダーのない構造
生成された makefile を移動先の開発環境で使用する、またはコードがファイルの相対位置を利用するため、移動先の開発環境において移動元の開発環境のフォルダー構造を維持しなければならない階層構造

階層構造を使用する場合、関数 packNGo によって 2 重の zip ファイルが作成されます。プライマリ zip ファイルの中に、次のセカンダリ zip ファイルが格納されます。

  • mlrFiles.zipmatlabroot フォルダー ツリー内にあるファイル

  • sDirFiles.zip — コード生成を開始したビルド フォルダー配下のファイル

  • otherFiles.zipmatlabroot または start フォルダー ツリー内にない必須ファイル

セカンダリ zip ファイルへのパスは、プライマリ zip ファイルのルート フォルダーからの相対パスとなり、移動元の開発環境のフォルダー構造が維持されます。

参考

関数

関連するトピック