生成コードの MATLAB Coder の最適化
生成コードの実行速度およびメモリ使用を改善するために、MATLAB® Coder™ では次の最適化方法を導入しています。
定数畳み込み
コード ジェネレーターは、可能な場合、MATLAB コード内の式のうち、コンパイル時の定数を伴うもののみを評価します。これらの式は、生成コード内で評価結果で置き換えられます。この動作は定数畳み込みといいます。定数畳み込みによって、生成コードの実行中に定数を評価する必要がなくなります。
次の例では、コード生成中に定数が畳み込まれる MATLAB コードを示します。関数 MultiplyConstant
は行列内の各要素にスカラー定数を乗算します。この関数は、コンパイル時の 3 つの定数 a
、b
および c
の積を使用して、この定数を評価します。
function out=MultiplyConstant(in) %#codegen a=pi^4; b=1/factorial(4); c=exp(-1); out=in.*(a*b*c); end
コード ジェネレーターはコンパイル時の定数 a
、b
および c
を含む式を評価します。これらの式は、生成コード内で評価結果と置き換えられます。
定数畳み込みは、式にスカラーのみが含まれている場合に実行されます。それ以外で式における定数畳み込みを明示的に実行させるには、関数 coder.const
を使用します。
定数畳み込みの制御
コマンド ラインまたは [プロジェクトの設定] ダイアログ ボックスから定数の畳み込みが可能な命令の最大数を制御できます。
コマンド ラインでコード生成のための構成オブジェクトを作成します。
ConstantFoldingTimeout
プロパティを求める値に設定します。cfg=coder.config('lib'); cfg.ConstantFoldingTimeout = 200;
アプリを使用して、[プロジェクトの設定] ダイアログ ボックスの [すべての設定] タブで、[定数畳み込みのタイムアウト] フィールドを必要な値に設定します。
ループの統合
コード ジェネレーターは、可能な場合、実行回数が等しい複数の連続するループを生成コード内で 1 つのループに統合します。この最適化により、ループのオーバーヘッドが軽減されます。
次のコードには連続ループが含まれており、コード生成中に統合されます。関数 SumAndProduct
は配列 Arr
の要素の和と積を評価します。また、2 つの独立したループを使用して和 y_f_sum
と積 y_f_prod
を評価します。
function [y_f_sum,y_f_prod] = SumAndProduct(Arr) %#codegen y_f_sum = 0; y_f_prod = 1; for i = 1:length(Arr) y_f_sum = y_f_sum+Arr(i); end for i = 1:length(Arr) y_f_prod = y_f_prod*Arr(i); end
この MATLAB コードから生成されたコードは、1 つのループ内で和と積を評価します。
連続する行列演算の統合
コード ジェネレーターは、可能な場合、対象の MATLAB コード内の連続する行列演算を生成コード内で 1 つのループ演算に変換します。この最適化により、独立したループ内で行列演算の実行時に発生する過度なループ オーバーヘッドが軽減されます。
次の例は、連続する行列演算が実施されるコードを含んでいます。関数 ManipulateMatrix
は行列 Mat
内の各要素に factor
を乗算します。この関数は、結果のすべての要素に対して、shift
を追加します。
function Res=ManipulateMatrix(Mat,factor,shift) Res=Mat*factor; Res=Res+shift; end
生成コードでは、乗算と加算が 1 つのループ演算に統合されています。
到達不能コードの除去
コード ジェネレーターは、可能な場合、MATLAB コード内の到達不能な手続きからのコード生成を抑制します。たとえば、if, elseif, else
ステートメントの 1 つの分岐が到達不能な場合、その分岐に対するコードは生成されません。
次の例には到達不能なコードが含まれていて、コード生成中に除去されます。関数 SaturateValue
は入力 x
の範囲に基づいて値を返します。
function y_b = SaturateValue(x) %#codegen if x>0 y_b = x; elseif x>10 %This is redundant y_b = 10; else y_b = -x; end
if
、elseif
、else
ステートメントの 2 番目の分岐は到達不能です。変数 x
が 10 より大きければ 0 よりも大きいので、最初の分岐は 2 番目の分岐よりも優先的に実行されます。
MATLAB Coder は到達不能な 2 番目の分岐のコードを生成しません。
memcpy
呼び出し
連続する配列要素をコピーする生成されたコードを最適化するために、コード ジェネレーターはこのコードを memcpy
呼び出しに置き換えることを試みます。memcpy
呼び出しは、for
ループまたは複数の連続する要素の代入などのコードよりもさらに効率的です。
memcpy 最適化を参照してください。
memset
呼び出し
リテラル定数を連続する配列要素に代入する生成されたコードを最適化するために、コード ジェネレーターはこのコードを memset
呼び出しに置き換えることを試みます。memset
呼び出しは、for
ループまたは複数の連続する要素の代入などのコードよりもさらに効率的です。
memset の最適化を参照してください。