このページの翻訳は最新ではありません。ここをクリックして,英語の最新版を参照してください。
MATLAB®コードを効率良く動作するC / c++コードに変換するため,コードジェネレーターに,元のソースコードと生成後のコードの動作が意図的に異なる(場合によっては異なる結果が出る)ように最適化が導入されています。
次のような相違点があります。
プログラムを実行すると,実行時エラーチェックで次の相違点が検出される可能性があります。既定では,実行時エラーチェックは墨西哥人コードに対して有効化され,スタンドアロンC / c++コードに対しては無効化されています。コードを配布する前に相違点を識別して解決できるように,コードジェネレーターは,潜在的な相違として相違点のサブセットを報告します。
行列の特異値分解や固有値分解などの特定の数学演算では,複数の解が得られる場合があります。このような演算を実装する2つの異なるアルゴリズムは,同じ入力値に対して異なる出力を返す場合があります。同じアルゴリズムの2つの異なる実装でも同じ動作になることがあります。
このような数学演算では,生成されたコードとMATLABの対応する関数が同じ入力値に対して異なる出力を返す場合があります。関数がこの動作を示すかどうかを確認するには,対応する関数のリファレンスページで,「拡張機能」の“C / c++コードの生成”セクションを参照してください。このような関数の例には,圣言会
やeig
などがあります。
答
への書き込み出力引数を指定せずに出力を返すMATLABコードを実行すると,MATLABは変数答
に出力を暗黙的に書き込みます。変数答
が既にワークスペースに存在する場合,MATLABはその値を返された出力に更新します。
このようなMATLABコードから生成されたコードは,変数答
に出力を暗黙的に書き込みません。
たとえば1行目で変数答
を明示的に作成するMATLAB関数喷火
を定義します。この関数は2行目が実行されると答
の値を暗黙的に更新します。
函数喷火% # codegenans = 1;2;disp (ans);结束
コマンドラインで喷火
を実行します。答
の最終値2
がコマンドラインに表示されます。
喷火
2
喷火
から墨西哥人関数を生成します。
codegen喷火
生成された墨西哥人関数foo_mex
を実行します。この関数は変数答
を明示的に作成し,その変数に値1
を代入します。ただし,foo_mex
は答
の値を2
に暗黙的に更新しません。
foo_mex
1
MATLABコードで論理演算子&
および|
が大かっこ([
と]
)内に配置されているとします。このようなコードパターンの場合,生成コードではこれらの論理演算子のショートサーキットの動作は使用されませんが,MATLABの実行ではショートサーキットの動作が使用されることがあります。論理ショートサーキットを参照してください。
たとえば,如果……
ブロックの条件式の大かっこ内で&
演算子を使用するMATLAB関数喷火
を定義します。
函数喷火如果[returnsFalse () & hasSideEffects ())结束结束函数out = returnsFalse;结束函数out = hasSideEffects out = true;disp ("这是我的绳子");结束
&
演算子の最初の引数は常に假
で,条件式の値を決定します。そのため,MATLABの実行ではショートサーキットが使用され,2番目の引数は評価されません。したがって,喷火
では実行時に関数hasSideEffects
は呼び出されず,コマンドラインに何も表示されません。
喷火
の墨西哥人関数を生成します。生成された墨西哥人関数foo_mex
を呼び出します。
foo_mex
这是我的绳子
生成コードでは,ショートサーキットは使用されません。したがって,関数hasSideEffects
が呼び出され,コマンドラインに文字列が表示されます。
为
ループの終了値がループインデックスのデータ型の最大値または最小値と等しいか近いと仮定します。生成コードでは,ループインデックスの最後のインクリメントまたはデクリメントによって,インデックス変数のオーバーフローが発生する可能性があります。インデックスのオーバーフローの結果,無限ループが発生する可能性があります。
メモリの整合性チェックが有効になっている場合,ループインデックスのオーバーフローが発生する可能性があることをコードジェネレーターが検出すると,エラーが報告されます。ソフトウェアのエラーチェックは保守的です。ループインデックスのオーバーフローを誤って報告する可能性があります。既定では、メモリの整合性チェックは MEX コードに対して有効化され、スタンドアロン C/C++ コードに対しては無効化されています。MATLABで墨西哥人関数をテストする理由および生成独立的C/ c++代码,检测和报告运行时错误を参照してください。
ループインデックスのオーバーフローを回避するには,次の表の回避方法を使用してください。
オーバーフローを引き起こす可能性のあるループ条件 | 回避方法 |
---|---|
|
ループがあらゆる整数データ型に対応する必要がない場合,終了値が整数データ型の最大値と等しくならないようにループを書き換えます。たとえば, N = intmax (k = N-10 int16): N k = 1:10 |
|
ループがあらゆる整数データ型に対応する必要がない場合,終了値が整数データ型の最小値と等しくならないようにループを書き換えます。たとえば, N = intmin (int32) k = N + 10: 1: N k = 10: 1:1 |
|
ループがあらゆる整数データ型に対応しなければならない場合は,ループの開始値,ステップ,および終了値の型をより大きな整数または双の値にキャストします。たとえば,次のコードを書き換えます。 M = intmin(“int16”);N = intmax(“int16”);for k=M:N %循环体结束 M = intmin(“int16”);N = intmax(“int16”);for k=int32(M):int32(N) %循环体结束 |
|
ループを書き直し,最後のループ反復におけるループインデックスが終了値と等しくなるようにします。 |
为
ループのインデックス付けMATLABコードで,コロン演算子がある为
ループのインデックス付けを行うとします。ここでは,コロンオペランドの少なくとも1つが单一型のオペランドで,反復回数はflintmax('单')= 16777216
を超えます。これらすべての条件が満たされている場合,コード生成でランタイムエラーまたはコンパイル時エラーが発生する可能性があります。これは,生成されたコードで計算されるループインデックス変数の値がMATLABで計算される値とは異なることが原因です。
たとえば,以下のMATLABコードについて考えます。
函数j = singlePIndex n = flintmax(“单一”) + 2;j =单(0);为I = single(1):single(n) j = I;结束结束
このコードの抜粋はMATLABで実行されていますが,生成されたコードではループインデックス変数我
に対する値が異なる方法で計算されているため,コンパイル時エラーまたはランタイムエラーが発生します。コードジェネレーターでコンパイル時エラーまたはランタイムエラーが表示され,この不一致を回避するためにコードの生成または実行が停止します。
この不一致を回避するには,单一型のオペランドを双型または整数型のオペランドに置き換えます。
ランタイムエラーの詳細については,生成独立的C/ c++代码,检测和报告运行时错误を参照してください。
为
ループのインデックスMATLABコードと生成されたコードでは,为
ループの実行が完了した後,インデックス変数の値は为
ループの最終反復時の値と等しくなります。
MATLABでループが実行されない場合,インデックス変数の値は[](空行列)として保存されます。生成されたコードでループが実行されない場合、インデックス変数の値は MATLAB のインデックス変数とは異なります。
为
ループの開始変数と終了変数を実行時に指定する場合,インデックス変数の値は範囲の開始値と等しくなります。たとえば,以下のMATLABコードについて考えます。
函数= indexTest (a, b)为我= a: b结束=我;结束
一个
とb
が1
と-1
として渡されると仮定します。为
ループは実行されません。MATLABでは,出
に[]が代入されます。生成されたコードでは,出
に一个
の値1
が代入されます。
为
ループの開始値と終了値をコンパイルの前に指定する場合,インデックス変数の値は0
と等しくなります。以下のMATLABコードについて考えます。
函数出= indexTest为i = 1: 1结束=我;结束
この関数を呼び出すと仮定します。MATLABでは,出
に[]が代入されます。生成されたコードでは,出
に値0
が代入されます。
MATLABは16ビットの文字をサポートしていますが,生成されたコードでは文字をC言語などの多くの埋め込み型言語の標準サイズである8ビットで表現します。コード生成での文字のエンコードを参照してください。
生成されたコードは,式の評価順番を強制しません。ほとんどの式において,評価の順序は重要な意味をもちません。副作用を含む式では,生成コードと元のMATLABコードとで副作用が異なる順序で生成される場合があります。副作用を伴う式には,以下のようなものがあります。
永続変数またはグローバル変数を変更する
画面にデータを表示する
データをファイルに書き込む
ハンドルクラスのオブジェクトのプロパティを変更する
また,生成されたコードは,ショートサーキットしない論理演算子の実行順番を強制しません。
結果を予測しやすくするために,実行順序に依存する式を複数のステートメントに分割してコードを書くことをお勧めします。
たとえば,次のコードを書き換えます。
A = f1() + f2();
以下のように書き換えます。
一个= f1 ();A = A + f2();
こうすると,生成されたコードはf1
を呼び出してから,f2
を呼び出します。
多出力関数呼び出し出力を,相互に依存していない複数の変数に代入します。たとえば,次のコードを書き換えます。
[y, y.f, y.g] = foo;
これは,次のように書き換えられます。
[y, a, b] = foo;y.f =一个;y.g = b;
细胞配列の複数のセルの内容にアクセスする場合,その結果を相互に依存していない変数に代入します。たとえば,次のコードを書き換えます。
[y, y.f, y.g] = z{:};
以下のように書き換えます。
[y, a, b] = z{:};y.f =一个;y.g = b;
MATLABとコード生成では,記号@
の後の名前を解決する際に異なる優先順位規則に従います。これらの規則は無名関数には適用されません。優先順位規則を次の表にまとめます。
式 | MATLABでの優先順位 | コード生成での優先順位 |
---|---|---|
ピリオドを含まない式(@x など) |
入れ子関数,ローカル関数,プライベート関数,パス関数 |
ローカル変数,入れ子関数,ローカル関数,プライベート関数,パス関数 |
ピリオドを1つだけ含む式(@x.y など) |
ローカル変数,パス関数 |
ローカル変数,パス関数(MATLABと同じ) |
複数のピリオドを含む式(@x.y.z など) |
パス関数 |
ローカル変数,パス関数 |
x
がそれ自体が関数ハンドルとなるローカル変数である場合,生成されたコードとMATLABでは式@x
の解釈が異なります。
MATLABではエラーが発生します。
生成されたコードでは@x
がx
自体の関数ハンドルとして解釈されます。
次の例では2つのピリオドを含む式の動作におけるこの相違点を示します。
現在の作業フォルダーにパッケージx
が含まれ,これに関数z
を含む別のパッケージy
が含まれていると仮定します。また,現在の作業フォルダーには,コードの生成対象となるエントリポイント関数喷火
も含まれています。
ファイル喷火
の定義は次のとおりです。
函数Out = foo X.Y.Z = @()'x.y.z是一个匿名函数';= g (x);结束函数Out = g(x) f = @x.y.z;= f ();结束
関数z
の定義は次のとおりです。
函数Out = z Out ='x.y.z是一个包函数';结束
喷火
の墨西哥人関数を生成します。生成された墨西哥人関数foo_mex
とMATLAB関数喷火
の両方を個別に呼び出します。
codegen喷火foo_mex foo
Ans = 'x.y.z is an匿名函数' Ans = 'x.y.z是一个包函数'
生成されたコードによって最初の出力が生成されます。MATLABによって 2 番目の出力が生成されます。コード生成では、@x.y.z
は喷火
で定義されているローカル変数x
に解決されます。MATLABでは、@x.y.z
はパッケージx.y
内のz
に解決されます。
生成されたコードの終了動作は,MATLABソースコードの動作と一致しません。たとえば,無限ループに副次的影響がない場合、無限ループは最適化によって生成されたコードから除去されます。その結果、対応する MATLAB コードが終了しなくても生成コードは終了する場合があります。
可変サイズのN次元配列では,関数大小
で返す結果が,生成されたコードとMATLABソースコードで異なる場合があります。関数大小
は,生成されたコードでは後に1を続けて返すことがありますが(大きさが1の次元),MATLABでは後続する1は常に切り捨てられます。たとえばN次元の配列X
が次元[4 2 1 1]
をもっている場合,大小(X)
は,生成されたコードでは[4 2 1 1]
を返す場合がありますが,MATLABでは常に(4 - 2)
を返します。可変サイズのN次元配列のサイズを判定する上でのMATLABとの非互換性を参照してください。
空の配列のサイズは,生成コードとMATLABソースコードでは異なる場合があります。空配列のサイズを判定する際のMATLABとの非互換性を参照してください。
配列のすべての要素を削除することで,空の配列が生成されます。この空の配列のサイズは,生成コードとMATLABソースコードでは異なる場合があります。
ケース | コード例 | MATLABでの空配列のサイズ | 生成コードでの空配列のサイズ |
---|---|---|---|
结肠 演算子 (: )を使用してm行n列の配列のすべての要素を削除する。 |
coder.varsize (“X”(4, 4), [1]);X = 0 (2);X (:) = [];
|
0-by-0 |
1-by-0 |
结肠 演算子 (: )を使用して行ベクトルのすべての要素を削除する。 |
coder.varsize (“X”[1,4], [0, 1]);X = 0 (1,4);X (:) = [];
|
0-by-0 |
1-by-0 |
结肠 演算子 (: )を使用して列ベクトルのすべての要素を削除する。 |
coder.varsize (“X”(4,1), (1,0));X = 0 (4,1);X (:) = [];
|
0-by-0 |
0-by-1 |
一度に1つずつ要素を削除して列ベクトルのすべての要素を削除する。 |
coder.varsize (“X”(4,1), (1,0));X = 0 (4,1);为i = 1:4 X(1)= [];结束 |
1-by-0 |
0-by-1 |
MATLABコードに单一型と双型のオペランドをもつ要素単位の二項演算が含まれる場合,生成コードの結果がMATLABの結果と同じにならないことがあります。
このような演算について,MATLABでは,両オペランドを双型にキャストし,双型で演算を実行します。MATLABは実行結果を单一型にキャストし,その結果を返します。
生成コードでは、双型のオペランドを单一型にキャストします。そして2つの单一型で演算を実行し,その結果を返します。
たとえば,要素単位の二項演算+
を呼び出すMATLAB関数喷火
を定義します。
函数Out = foo(a,b) Out = a + b;结束
单一型の変数s1
と、双型の変数v1
を定義します。单一型の入力と双型の入力を受け入れる喷火
の墨西哥人関数を生成します。
s1 =单(1.4 e32);d1 = -5.305 e + 32;codegen喷火arg游戏{s1, d1}
入力s1
およびd1
を指定して,喷火
とfoo_mex
の両方を呼び出します。2つの結果を比較します。
毫升= foo (s1、d1);多层陶瓷= foo_mex (s1、d1);毫升= =多层陶瓷
逻辑0
比較の出力は逻辑0
になります。これは,これらの入力について,生成コードとMATLABで異なる結果を生成することを示しています。
生成されたコードは,以下の場合のMATLABにおける浮動小数点の数値結果とは,異なる可能性があります。
生成されたコードでは,南
および正
の値が数学的に無意味の場合,値のパターンがMATLABコードと異なる場合があります。たとえば,MATLAB出力に南
が含まれる場合,生成されたコードの出力にも南
が含まれますが,必ずしも同じ場所に含まれるとは限りません。
南
のビットパターンがMATLABコードの出力と生成されたコードで異なる場合があります。それは,コードの生成に使用されるC99標準の数学ライブラリが,すべての実装で南
に一意のビットパターンを指定しないからです。MATLAB出力と SIL 出力または PIL 出力など異なる実装でビット パターンを比較しないでください。
浮動小数点型の場合,値0
は正の記号または負の記号のいずれかをもちます。算術的に,0
は0
と等価ですが,一部の演算では0入力の符号が区別されます。たとえば,rdivide
、量化
、atan2d
、角
がこれに該当します。0
で除算すると正
が生成されますが,0
で除算すると负
が生成されます。同様に,atan2d (0, 1)
では180
が生成されますが,atan2d (0, 1)
では-180年
が生成されます。
浮動小数点変数が適切な範囲の整数値のみを取得することが,コードジェネレーターによって検出される場合,コードジェネレーターでは生成されたコード内の変数に整数型を使用できます。コードジェネレーターで変数に整数型が使用されると,その変数は0
を+0
として保存します。これは,整数型には値0
の記号が保存されないためです。生成されたコードで変数が浮動小数点型にキャストし直されると、0
の記号は正になります。0
で除算すると负
ではなく正
が生成されます。同様に,atan2d (0, 1)
では-180年
ではなく,180
が生成されます。
生成されたコードで0
がMATLABとは異なる方法で扱われる他のコンテキストがあります。たとえば,MATLABコードで,z = min (x, y)
を使用して2つの双型のスカラーx
とy
の最小値を計算するとします。生成されたCコードの対応する行はz = fmin (x, y)
となる可能性があります。関数fmin
はCコンパイラのランタイム数学ライブラリで定義されています。比較演算子0.0 = = -0.0
は真正的
をC / c++で返すため,fmin
のコンパイラの実装ではfmin (0.0, -0.0)
に対して0.0
または-0.0
のいずれかが返される可能性があります。
関数coder.target
は,生成されたコードとMATLABで異なる値を返します。これは,関数がMATLABで実行されているのか,それともシミュレーションまたはコード生成ターゲット用にコンパイルされたのかを判断できるようにすることを目的としています。coder.target
を参照してください。
MATLABでは,クラスの読み込み時にクラスの既定値を計算してからコード生成を行います。コードジェネレーターでは,MATLABで計算される値が使用されます。既定値は再計算されません。プロパティ定義で関数呼び出しを使って初期値を計算する場合,コードジェネレーターはこの関数を実行しません。関数にグローバル変数や永続変数の変更といった副作用がある場合、生成されたコードから得られる結果が MATLAB の結果とは異なる可能性があります。詳細は、コード生成のためのクラスプロパティの定義を参照してください。
ハンドルオブジェクトのプロパティに値を割り当てるときに,そのプロパティ自体が別のオブジェクトのプロパティでもある場合,生成されたコードは,MATLABが呼び出さないハンドルクラスの设置メソッドを呼び出すことができます。
たとえば,x
がハンドルオブジェクト,巴勒斯坦权力机构
がオブジェクト,pb
がハンドルオブジェクト,个人电脑
がpb
のプロパティになるように,一連の変数を定義すると仮定します。以下のように,入れ子にされたプロパティの割り当てを行います。
x.pa.pb.pc = 0;
この場合,生成されたコードはオブジェクトpb
の设置メソッドとx
の设置メソッドを呼び出します。MATLABはpb
の设置メソッドのみを呼び出します。
生成されたコードでのハンドルクラスのデストラクターの動作は,次の状況ではMATLABでの動作とは異なる場合があります。
複数の独立したオブジェクトを破棄する順序は,生成されたコードとMATLABでは異なる場合があります。
生成されたコードでのオブジェクトの存続期間は,MATLABでの存続期間と異なる可能性があります。
生成されたコードは,部分的に作成されたオブジェクトを破棄しません。ハンドルオブジェクトが実行時に完全に作成されていない場合,生成されたコードはエラーメッセージを作成しますが,そのオブジェクトの删除
メソッドは呼び出しません。系统对象™について,setupImpl
で実行時エラーがある場合,生成されたコードは,そのオブジェクトのreleaseImpl
は呼び出しません。
MATLABは,删除
メソッドを呼び出して,部分的に作成されたオブジェクトを破棄します。
詳細については,ハンドルクラスデストラクターのコード生成を参照してください。
コード生成時の可変サイズのサポートに関するMATLABとの非互換性を参照してください。
複素数データのコード生成を参照してください。
双
への変換複数の連続する単項演算子を含をむ字符串双
に変換すると,MATLABと生成されたコードで結果が異なる場合があります。次の関数を考えてみます。
函数Out = foo(op) Out = double(op + 1);结束
入力値”——“
の場合,関数によって字符串“- 1”
が双
に変換されます。MATLABでは、回答が南
になります。生成されたコードの回答は1
です。