Main Content

生成されたコードでの関数入力のデータ コピーの回避

同じ変数を入力と出力の両方に使用する関数を書くことで、生成コード内のコピーの数を減らすことができます。以下に例を示します。

function A = foo( A, B ) %#codegen
A = A * B;
end

このコードの書き方は、参照パラメーターの最適化を使用しています。変数が入力と出力の両方として機能する場合、生成されたコードにおいて、入力を一時変数に重複してコピーすることなく、この変数を参照で渡します。前述の例では、入力 A は関数 foo の出力としても使用されるため、生成コード内で参照渡しされます。

...
/* Function Definitions */
void foo(double *A, double B)
{
    *A *= B;
}
...

参照パラメーターの最適化により、特に参照渡しされる変数が大きなデータ構造体の場合に、メモリ使用量および実行時間を削減することができます。呼び出し側でこれらの恩恵を受けるには、入力と出力に同じ変数を指定して関数を呼び出します。

一方、この最適化を使用しないように関数 foo を以下のように書き換えるとします。

function y = foo2( A, B ) %#codegen
y = A * B;
end

生成されたコードは入力を値渡しで行い、出力の値を返します。

...
/* Function Definitions */
double foo2(double A, double B)
{
   return A * B;
}
...

場合によっては、関数の出力は、入力に変更を加えただけの形にできないことがあります。入力がそれ以降関数内で使用されない場合は、入力のコピーを作成して操作するのではなく、入力を操作するようにコードを変更できます。ひとつの方法として、関数に追加の戻り値を作成します。たとえば、以下のコードについて考えます。

function y1=foo(u1) %#codegen
  x1=u1+1;
  y1=bar(x1);
end

function y2=bar(u2)
  % Since foo does not use x1 later in the function,
  % it would be optimal to do this operation in place
  x2=u2.*2;
  % The change in dimensions in the following code
  % means that it cannot be done in place
  y2=[x2,x2];
end

コードを変更して、冗長なコピーを除去できます。

function y1=foo(u1) %#codegen
  u1=u1+1;
  [y1, u1]=bar(u1);
end

function [y2, u2]=bar(u2)
    u2=u2.*2;
  % The change in dimensions in the following code
  % still means that it cannot be done in place
  y2=[u2,u2];
end

参照パラメーターの最適化は定数入力に適用されません。同じ変数が入力と出力の両方で、入力が定数の場合、コード ジェネレーターでは出力が個別の変数として扱われます。たとえば、関数 foo について考えます。

function A = foo( A, B ) %#codegen
A = A * B;
end

A が定数値 2 をもつコードを生成します。

codegen -config:lib foo -args {coder.Constant(2) 3} -report

生成されたコードは、定数 A を定義し、出力の値を返します。

...
#define A                              (2.0)
...
double foo(double B)
{
  return A * B;
}
...

関連するトピック