Main Content

生成コードの MATLAB Coder の最適化

生成コードの実行速度およびメモリ使用を改善するために、MATLAB® Coder™ では次の最適化方法を導入しています。

定数畳み込み

コード ジェネレーターは、可能な場合、MATLAB コード内の式のうち、コンパイル時の定数を伴うもののみを評価します。これらの式は、生成コード内で評価結果で置き換えられます。この動作は定数畳み込みといいます。定数畳み込みによって、生成コードの実行中に定数を評価する必要がなくなります。

次の例では、コード生成中に定数が畳み込まれる MATLAB コードを示します。関数 MultiplyConstant は行列内の各要素にスカラー定数を乗算します。この関数は、コンパイル時の 3 つの定数 ab および c の積を使用して、この定数を評価します。

function out=MultiplyConstant(in) %#codegen
 a=pi^4;
 b=1/factorial(4);
 c=exp(-1);
 out=in.*(a*b*c);
end

コード ジェネレーターはコンパイル時の定数 ab および 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

ifelseifelse ステートメントの 2 番目の分岐は到達不能です。変数 x が 10 より大きければ 0 よりも大きいので、最初の分岐は 2 番目の分岐よりも優先的に実行されます。

MATLAB Coder は到達不能な 2 番目の分岐のコードを生成しません。

memcpy 呼び出し

連続する配列要素をコピーする生成されたコードを最適化するために、コード ジェネレーターはこのコードを memcpy 呼び出しに置き換えることを試みます。memcpy 呼び出しは、for ループまたは複数の連続する要素の代入などのコードよりもさらに効率的です。

memcpy 最適化を参照してください。

memset 呼び出し

リテラル定数を連続する配列要素に代入する生成されたコードを最適化するために、コード ジェネレーターはこのコードを memset 呼び出しに置き換えることを試みます。memset 呼び出しは、for ループまたは複数の連続する要素の代入などのコードよりもさらに効率的です。

memset の最適化を参照してください。