Main Content

生成コードでの暗黙的な拡張の最適化

生成コードでの暗黙的な拡張は既定で有効になっています。暗黙的な拡張を実行するためにコード ジェネレーターで生成コードに変更が加えられます。この生成コードの変更でオペランドを拡張するコードが追加される場合があります。オペランドの拡張は生成コードのパフォーマンスに影響することがあります。暗黙的な拡張を有効にしたコードの生成 (MATLAB Coder)を参照してください。

暗黙的な拡張により、サポートされる演算子や関数からの出力のサイズが変わり、ワークフローでサイズおよび型の不一致エラーが発生することがあります。

生成コードで暗黙的な拡張を有効にする対象を詳細に制御するには、MATLAB® コードで次の関数を使用します。

たとえば、次のコードの抜粋について考えます。関数 vector_sum はサイズに互換性がある 2 つの配列の和を求めます。

function out = vector_sum(a,b)
out = b + a;
end

オペランド a および b の型の定義は次のとおりです。

a_type = coder.typeof(1,[2 1])       %size: 2x1
b_type = coder.typeof(1,[2 Inf])     %size: 2x:inf

暗黙的な拡張がない場合、変数 out のサイズは 2x1 として計算されます。

Image of the Code Generation Report while hovering over the plus operation. A dialog box generated from the operation outlines the size, class, and complexity of the operation. The size of the output variable out without implicit expansion is shown as 2 x 1.

暗黙的な拡張がある場合、変数 out のサイズは 2x:? として計算されます。

Image of the Code Generation Report while hovering over the plus operation. A dialog box generated from the operation outlines the size, class, and complexity. Also mentions that the dimensions shown in bold imply the possible use of implicit expansion. The size of the output variable, out, is shown as 2 x :?.

次のコードの抜粋は、関数 vector_sum の生成コードについて、暗黙的な拡張を無効にした場合と有効にした場合でどのように変わるかを示したものです。このコードを生成するには、オペランド a および b の型を次のように定義します。

a_type = coder.typeof(1,[1 Inf])       %size: 1x:inf
b_type = coder.typeof(1,[1 Inf])       %size: 1x:inf
暗黙的な拡張を無効にした生成コード暗黙的な拡張を有効にした生成コード
void vector_sum(const emxArray_real_T *a, const emxArray_real_T *b,
                emxArray_real_T *out)
{
  int i;
  int loop_ub;
  i = out->size[0] * out->size[1];
  out->size[0] = 1;
  out->size[1] = b->size[1];
  emxEnsureCapacity_real_T(out, i);
  loop_ub = b->size[1];
  for (i = 0; i < loop_ub; i++) {
    out->data[i] = b->data[i] + a->data[i];
  }
}
static void plus(emxArray_real_T *out, const emxArray_real_T *b,
                 const emxArray_real_T *a)
{
  int i;
  ....
  if (a->size[1] == 1) {
    out->size[1] = b->size[1];
  } else {
    out->size[1] = a->size[1];
  }
  ....
  if (a->size[1] == 1) {
    loop_ub = b->size[1];
  } else {
    loop_ub = a->size[1];
  }
  for (i = 0; i < loop_ub; i++) {
    out->data[i] = b->data[i * stride_0_1] + a->data[i * stride_1_1];
  }
}
void vector_sum(const emxArray_real_T *a, const emxArray_real_T *b,
                emxArray_real_T *out)
{
  int i;
  int loop_ub;
  if (b->size[1] == a->size[1]) {
    i = out->size[0] * out->size[1];
    out->size[0] = 1;
    out->size[1] = b->size[1];
    emxEnsureCapacity_real_T(out, i);
    loop_ub = b->size[1];
    for (i = 0; i < loop_ub; i++) {
      out->data[i] = b->data[i] + a->data[i];
    }
  } else {
    plus(out, b, a);
  }
}

coder.noImplicitExpansionInFunction を使用した指定した関数での暗黙的な拡張の無効化

暗黙的な拡張がプロジェクトでは必要で、特定の関数で必要ない場合、該当する関数内で coder.noImplicitExpansionInFunction (MATLAB Coder) を呼び出して、その関数の生成コードに対する暗黙的な拡張を無効にします。

たとえば、vector_sum に対して生成される次のコードでは暗黙的な拡張が適用されません。

MATLAB コードcoder.sameSizeBinaryOp を使用した生成コード
function out = vector_sum(a,b)
coder.noImplicitExpansionInFunction();
out = a + b;
end
a = coder.typeof(1,[1 Inf]) %size: 1x:inf
b = coder.typeof(1,[1 Inf]) %size: 1x:inf
codegen vector_sum -launchreport 
... -args {a,b} -config:lib
void vector_sum(const emxArray_real_T *a, 
const emxArray_real_T *b, emxArray_real_T *out)
{
  int i;
  int loop_ub;
  i = out->size[0] * out->size[1];
  out->size[0] = 1;
  out->size[1] = a->size[1];
  emxEnsureCapacity_real_T(out, i);
  loop_ub = a->size[1];
  for (i = 0; i < loop_ub; i++) {
    out->data[i] = a->data[i] + b->data[i];
  }
}

メモ

coder.noImplicitExpansionInFunction の場合、MATLAB コードでは暗黙的な拡張は無効になりません。生成コードでのみ暗黙的な拡張が無効になります。

coder.sameSizeBinaryOp を使用した特定の二項演算に対する暗黙的な拡張の無効化

エラー チェックを実行してオペランドが同じサイズであることを確認し、コード ジェネレーターでその関数に対して暗黙的に拡張されるコードが生成されないようにするには、関数 coder.sameSizeBinaryOp (MATLAB Coder) を使用します。

たとえば、次のコードの抜粋では、coder.sameSizeBinaryOp を使用して暗黙的な拡張なしで加算演算を適用しています。

MATLAB コード生成コード
function out = vector_sum(a,b)
out = coder.sameSizeBinaryOp(@plus, a, b);
end
a = coder.typeof(1,[1 Inf]) %size: 1x:inf
b = coder.typeof(1,[1 Inf]) %size: 1x:inf
codegen vector_sum -launchreport 
... -args {a,b} -config:lib
void vector_sum(const emxArray_real_T *a, 
const emxArray_real_T *b, emxArray_real_T *out)
{
  int i;
  int loop_ub;
  i = out->size[0] * out->size[1];
  out->size[0] = 1;
  out->size[1] = a->size[1];
  emxEnsureCapacity_real_T(out, i);
  loop_ub = a->size[1];
  for (i = 0; i < loop_ub; i++) {
    out->data[i] = a->data[i] + b->data[i];
  }
}

coder.sameSizeBinaryOp ではスカラー拡張はサポートされません。coder.sameSizeBinaryOp に与えられるオペランドのサイズは同じでなければなりません。

プロジェクトでの暗黙的な拡張の無効化

生成コードで暗黙的な拡張が必要ない場合や生成コードに影響する変更が望ましくない場合は、coder.config オブジェクトの EnableImplicitExpansion (MATLAB Coder) フラグを false に設定して暗黙的な拡張をオフにします。このフラグは既定では true に設定されています。

cfg = coder.config;
cfg.EnableImplicitExpansion = false;

Simulink® モデルで暗黙的な拡張を無効にするには、モデル全体のパラメーター [MATLAB 関数の暗黙的な拡張を有効にする]false に設定します。あるいは、次のコマンドを使用します。

set_param(gcs,'EnableImplicitExpansion',false);

メモ

暗黙的な拡張をオフにする前に、外部コードで暗黙的な拡張が使用されていないことを確認してください。プロジェクト全体で暗黙的な拡張を無効にしてコードを生成すると、プロジェクトに外部ソースからの MATLAB コードが含まれている場合にエラーの原因になる可能性があります。

参考

(MATLAB Coder) | (MATLAB Coder)

関連するトピック