このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。
可変サイズ データのためのコード生成
可変サイズ データは実行時にサイズが変化する可能性のあるデータです。MATLAB® Coder™ を使用して、可変サイズ データを使用している MATLAB コードから C/C++ コードを生成できます。MATLAB では、コード生成に対して制限付きと制限なしの可変サイズ データがサポートされています。"制限付き可変サイズ データ" には固定の上限があります。このデータはスタックで静的に割り当てることも、ヒープで動的に割り当てることもできます。"制限なしの可変サイズ データ" には上限が設定されていません。このデータはヒープで割り当てなければなりません。既定では、MEX コードおよび C/C++ コードの生成において可変サイズ データのサポートは有効で、構成可能なしきい値以上のサイズをもつ可変サイズ配列に対し動的なメモリの割り当てが有効になっています。
可変サイズ データのサポートの無効化
既定では、MEX および C/C++ コードの生成において、可変サイズ データのサポートは有効になっています。[プロジェクトの設定] ダイアログ ボックス、コマンド ラインから、またはダイアログ ボックスを使用して可変サイズの設定を変更します。
MATLAB Coder アプリの使用
[生成] ダイアログ ボックスを開くために、[コード生成] ページの [生成] 矢印
をクリックします。
[詳細設定] をクリックします。
[メモリ] タブで、[可変サイズを有効化] をオンまたはオフにします。
コマンド ラインの入力
コード生成の構成オブジェクトを作成します。たとえば、ライブラリの場合は以下のとおりです。
cfg = coder.config('lib');
EnableVariableSizing
オプションを次のように設定します。cfg.EnableVariableSizing = false;
-config
オプションを使用して、構成オブジェクトをcodegen
に渡します。codegen -config cfg foo
動的メモリ割り当ての制御
既定では、設定可能なしきい値以上のサイズをもつ可変サイズ配列に対して、動的メモリ割り当てが有効になっています。[プロジェクトの設定] ダイアログ ボックスまたはコマンド ラインから、動的メモリ割り当ての設定を変更できます。
MATLAB Coder アプリの使用
[生成] ダイアログ ボックスを開くために、[コード生成] ページの [生成] 矢印
をクリックします。
[詳細設定] をクリックします。
[メモリ] タブで、[動的メモリ割り当てを有効化] を次のいずれかのオプションに設定します。
設定 動作 false
動的メモリ割り当てが無効になります。可変サイズ データはスタックで静的に割り当てられます。 true
[動的メモリ割り当てしきい値] 以上のサイズをもつ可変サイズ配列に対して、動的メモリ割り当てが有効になります。このしきい値より小さいサイズの可変サイズ配列は、スタックで割り当てられます。 必要に応じて、[動的メモリ割り当てしきい値] を構成してメモリ割り当てを微調整できます。[動的メモリ割り当てしきい値] の値を
0
に設定すると、すべての可変サイズ データがヒープで動的に割り当てられます。
コマンド ラインの入力
コード生成の構成オブジェクトを作成します。たとえば、MEX 関数の場合は、以下のようになります。
mexcfg = coder.config('mex');
EnableDynamicMemoryAllocation
オプションを次のように設定します。設定 動作 mexcfg.EnableDynamicMemoryAllocation=false;
動的メモリ割り当てが無効になります。可変サイズ データはスタックで静的に割り当てられます。 mexcfg.EnableDynamicMemoryAllocation=true;
DynamicMemoryAllocationThreshold
パラメーターを使用して指定された値以上のサイズ (バイト単位) の可変サイズ配列に対して動的メモリ割り当てが有効になります。このしきい値より小さいサイズの可変サイズ配列は、スタックで割り当てられます。DynamicMemoryAllocationThreshold
オプションを構成してメモリ割り当てを微調整できます。DynamicMemoryAllocationThreshold
を0
に設定すると、すべての可変サイズ データがヒープで動的に割り当てられます。-config
オプションを使用して、構成オブジェクトをcodegen
に渡します。codegen -config mexcfg foo
可変サイズ データによる MATLAB 関数のコードの生成
はじめに MEX コードを生成して生成コードを検証し、次にプロトタイプの結果に満足できたらスタンドアロン コードを生成する基本ワークフローを以下に示します。
簡単な例を使用してこれらの手順を実行するには、ループ内でベクトルを拡張する MATLAB 関数のコードの生成を参照してください。
MATLAB エディターで、コンパイル命令
%#codegen
を関数の最上部に追加します。この命令は、以下を実行します。
MATLAB アルゴリズムのコードを生成することを示す。
コード生成中に潜在的なエラーを検出するために MATLAB コード アナライザーでのチェックをオンにする。
コード アナライザーで検出された問題を解決します。
場合によっては、コードでデータに固定サイズが割り当てられているときに、ループでの割り当てや連結によって後からデータが大きくなると、MATLAB コード アナライザーが警告を表示することがあります。実行時にデータのサイズが変化することが想定されている場合は、これらの警告を無視できます。
codegen
を使用して MEX 関数を生成し、生成されたコードを検証します。以下のコマンド ライン オプションを使用します。-args {coder.typeof...}
: 可変サイズ入力がある場合-report
: コード生成レポートを生成する場合
以下に例を示します。
このコマンドはcodegen -report foo -args {coder.typeof(0,[2 4],1)}
coder.typeof
を使用して関数foo
への可変サイズ入力を 1 つ指定します。最初の引数0
は、入力データ型 (double
) と実数/複素数 (real
) を示します。2 番目の引数[2 4]
は、サイズを示す 2 次元の行列です。3 番目の引数1
は、入力が可変サイズであることを示します。最初の次元の上限は 2 で、2 番目の次元の上限は 4 です。メモ
コンパイル中に
codegen
は定義後にサイズが変化した変数と構造体フィールドを検出し、これらが発生した場合はエラーとして報告します。さらに、codegen
は実行時チェックを実行し、データが上限を超えた場合はエラーを生成します。サイズ不一致エラーを解決します。
原因 解決方法 詳細 データのサイズがロックされた後にサイズを変更しようとした。 データを可変サイズとして宣言します。 サイズ不一致エラーの診断と修正を参照してください。 上限エラーを解決します。
原因 解決方法 詳細 MATLAB が上限を判断または計算できない。 上限を指定します。 可変サイズ配列の上限の指定とサイズ不一致エラーの診断と修正を参照してください。 MATLAB が制限なしの可変サイズ データの上限を計算しようとした。 制限なしのデータの場合は、動的メモリ割り当てを有効にします。 動的メモリ割り当ての制御を参照してください。 関数
codegen
を使用して C/C++ コードを生成します。
ループ内でベクトルを拡張する MATLAB 関数のコードの生成
MATLAB 関数 myuniquetol について
この例は、関数 myuniquetol
を使用します。この関数は、入力ベクトル A
のバージョンであるベクトル B
で返されます。ここで、各要素はそれぞれの許容誤差 tol
内で一意であるとします。ベクトル B
では、すべての i
と j
に対して abs
(B
(i
) - B
(j
)) > tol
となります。まず、入力ベクトル A
は最大 100 までの要素を格納できると想定します。
function B = myuniquetol(A, tol) A = sort(A); B = A(1); k = 1; for i = 2:length(A) if abs(A(k) - A(i)) > tol B = [B A(i)]; k = i; end end
手順 1: コード生成のコンパイル命令の追加
コンパイル命令 %#codegen
を関数の最上部に追加します。
function B = myuniquetol(A, tol) %#codegen A = sort(A); B = A(1); k = 1; for i = 2:length(A) if abs(A(k) - A(i)) > tol B = [B A(i)]; k = i; end end
手順 2: コード アナライザーで検出された問題の解決
コード アナライザーは変数 B
のサイズが for-
ループ内で変化する可能性を検出します。これにより、次の警告が表示されます。
The variable 'B' appears to change size on every loop iteration. Consider preallocating for speed.
この関数では、ベクトル B
はベクトル A
から値を追加するためサイズを拡大することが想定されます。したがって、この警告は無視できます。
手順 3: MEX コードの生成
C/C++ コードを生成する前に MEX コードを生成することをお勧めします。MEX コードを生成することによって、実行時には検出が難しくなるコード生成上の問題を特定できます。
myuniquetol
の MEX 関数を生成します。codegen -report myuniquetol -args {coder.typeof(0,[1 100],1),coder.typeof(0)}
コード生成は正常に実行されます。
codegen
で問題は検出されません。現在のフォルダーで、codegen
がmyuniquetol
の MEX 関数を生成し、コード生成レポートへのリンクを提供します。[レポートの表示] リンクをクリックします。
コード生成レポートで [変数] タブを選択します。
A
は上限が100
の可変サイズであることを指定したため、A
のサイズは1 行 :100 列
です。変数B
のサイズは1x:?
で、上限のない可変サイズであることが示されます。
手順 4: C コードの生成
可変サイズ入力の C コードを生成します。既定では、codegen
は、動的メモリ割り当てしきい値の 64 キロバイトより小さいサイズのデータに対してメモリを静的に割り当てます。データのサイズがしきい値以上の場合や制限なしの場合、codegen
はヒープでメモリを動的に割り当てます。
C ライブラリ生成の構成オプションを作成します。
cfg=coder.config('lib');
次のコマンドを実行します。
codegen -config cfg -report myuniquetol -args {coder.typeof(0,[1 100],1),coder.typeof(0)}
codegen
は、既定の場所codegen\lib\myuniquetol
にスタティック ライブラリを生成し、コード生成レポートへのリンクを提供します。[レポートの表示] リンクをクリックします。
生成ファイルのリストで、
myuniquetol.h
をクリックします。関数宣言は以下のとおりです。
extern void myuniquetol(const double A_data[], const int A_size[2], double tol, emxArray_real_T *B);
codegen
はA
のサイズを計算し、その最大サイズが既定の動的メモリ割り当てしきい値の 64 バイトより小さいため、このメモリを静的に割り当てます。生成されたコードには次が含まれます。double A_data[]
:A
の定義。int A_size[2]
: 入力の実際のサイズ。
コード ジェネレーターは、
B
が、上限が不明な可変サイズであると判断します。これはB
をemxArray_real_T
として表します。MATLAB は、生成されたコード内でemxArrays
を作成して相互作用のためのユーティリティ関数を提供します。詳細は、生成された関数インターフェイスでの C 配列の使用を参照してください。
手順 5: 出力ベクトルに対する上限の指定
入力 A
は上限が 100
の可変サイズであることを指定しました。このため、出力 B
を 100
要素よりも大きくすることはできません。
coder.varsize
を使用して、B
は上限が100
の可変サイズであることを示します。function B = myuniquetol(A, tol) %#codegen A = sort(A); coder.varsize('B', [1 100], [0 1]); B = A(1); k = 1; for i = 2:length(A) if abs(A(k) - A(i)) > tol B = [B A(i)]; k = i; end end
コードを生成します。
codegen -config cfg -report myuniquetol -args {coder.typeof(0,[1 100],1),coder.typeof(0)}
関数宣言は以下のとおりです。
extern void myuniquetol(const double A_data[], const int A_size[2], double tol, double B_data[], int B_size[2]);
コード ジェネレーターは、メモリを
B
に静的に割り当てます。B
のサイズをint B_size[2]
に格納します。
手順 6: 動的メモリ割り当てしきい値の変更
この手順では、動的メモリ割り当てしきい値を減らして、このしきい値を超える入力のコードを生成します。この手順では、A
の 2 番目の次元に上限 10000
があることを指定します。
B
の上限をA
の上限と一致するように変更します。function B = myuniquetol(A, tol) %#codegen A = sort(A); coder.varsize('B', [1 10000], [0 1]); B = A(1); k = 1; for i = 2:length(A) if abs(A(k) - A(i)) > tol B = [B A(i)]; k = i; end end
動的メモリ割り当てしきい値を 4 キロバイトに設定し、入力
A
のサイズがこのしきい値を超える場合のコードを生成します。cfg.DynamicMemoryAllocationThreshold=4096; codegen -config cfg -report myuniquetol -args {coder.typeof(0,[1 10000],1),coder.typeof(0)}
レポートで生成コードを表示します。現在、
A
とB
の最大サイズが動的メモリ割り当てしきい値を超えているため、codegen
はA
とB
をヒープで動的に割り当てます。生成されたコードでは、A
とB
は型emxArray_real_T
をもちます。extern void myuniquetol(const emxArray_real_T *A, double tol, emxArray_real_T *B);