Main Content

暗黙的な拡張を有効にしたコードの生成

暗黙的な拡張とは、互換性があるオペランドに対して要素単位の演算を適用するために自動で行われるサイズ変更のことです。すべての次元で配列の次元サイズが同じであるか、いずれかの次元サイズが 1 である場合、2 つの次元のサイズには互換性があります。基本的な演算で互換性のある配列サイズを参照してください。

生成コードでの暗黙的な拡張は既定で有効になっています。暗黙的な拡張を有効にして生成されたコードは、暗黙的な拡張を無効にして生成されたコードと次の点において異なることがあります。

  • 出力サイズ

  • 追加のコード生成

  • パフォーマンスの変化

可変サイズの動的な配列の場合、実行時に暗黙的な拡張を達成するために、生成コードにこれらの変化が見られます。

固定サイズの定数の配列の場合、オペランドの値とサイズがコンパイル時に既知であるため、暗黙的に拡張される出力を計算するために生成されるコードに追加のコード生成は必要なく、パフォーマンスの変化もありません。

生成コードでの暗黙的な拡張の制御については、生成コードでの暗黙的な拡張の最適化を参照してください。

出力サイズ

暗黙的な拡張では、要素単位の演算を適用するためにオペランドが自動的に拡張されます。たとえば、サイズに互換性がある次の入力の型について考えます。

a_type = coder.typeof(1,[2 1]);
b_type = coder.typeof(1,[2 inf]);

これらの 2 つのオペランドに対する二項演算で暗黙的な拡張が有効な場合、a_type の 2 番目の次元が自動的に拡張され、出力サイズが 2 行 Inf 列になります。暗黙的な拡張が無効な場合は、a_type の 2 番目の次元が自動的に拡張されず、出力サイズは 2 行 1 列になります。

生成コードでの暗黙的な拡張を無効にして作成された既存のワークフローの場合、暗黙的な拡張を有効にして同じ MATLAB® コードのコードを生成すると、サイズ不一致エラーが生成されるか、二項演算および二項関数からの出力のサイズが変わることがあります。サイズ不一致エラーのトラブルシューティングについては、可変サイズ データ エラーの診断と修正を参照してください。

追加のコード生成

暗黙的な拡張では、オペランドのサイズに互換性がある場合にオペランドを自動的に拡張できます。このサイズ変更を実行するために、オペランドの拡張を可能にするコードが生成コードに導入されます。

たとえば、次のコードの抜粋について考えます。関数 vector_sum は 2 つの配列の和を求めます。

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

次のように定義される可変サイズの動的な配列について考えます。

c_type = coder.typeof(1,[1 Inf]);

次のコマンドを使用して vector_sum のコードを生成します。

codegen vector_sum -args {c_type, c_type} -config:lib -report

この関数の暗黙的な拡張ありの場合の生成コードは次のとおりです。

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);
  }
}

この関数の暗黙的な拡張なしの場合の生成コードは次のとおりです。

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]; 
  }
}

暗黙的な拡張が有効な場合、コード ジェネレーターは、サイズ変更と出力の計算を行うサポート関数 (この例では plus) を作成します。

ほとんどの場合、暗黙的な拡張を実行するサポート関数には、それがサポートする二項演算に基づいて名前が付けられます。前の例の式 out = a + bout = a - b に変更すると、サポート関数の名前は minus に変わります。

一部のサポート関数は expand_op という名前になる場合もあります。op は二項演算を示します。前の例の式 out = a + bout = max(a,b) に置き換えると、生成コードにおけるサポート関数の名前は expand_max に変わります。

式に含まれる複数の演算で暗黙的な拡張が必要な場合は、生成コードに binary_expand_op という名前のサポート関数が含まれます。これらのサポート関数により、オペランドのサイズが変更され、二項演算が適用されます。

特定の二項演算および二項関数を暗黙的な拡張なしで適用する場合は、coder.sameSizeBinaryOp を使用します。この関数を適用するために生成されるコードには、オペランドを拡張する追加のコードは含まれません。この関数の出力では MATLAB でオペランドが拡張されません。この関数ではスカラー拡張はサポートされません。オペランドのサイズは同じでなければなりません。

生成コードの特定の関数に含まれるすべての二項演算について暗黙的な拡張を無効にする場合は、その関数で coder.noImplicitExpansionInFunction を呼び出します。MATLAB コードでの暗黙的な拡張は有効なままになります。

パフォーマンスの変化

暗黙的な拡張を有効にして生成されたコードは、暗黙的な拡張を無効にした場合とパフォーマンスが異なることがあります。暗黙的な拡張を使用する生成コードへの入力に応じて、出力の評価にかかる時間が長くなる場合があります。

暗黙的な拡張が原因で生成コードがワークフローのパフォーマンス要件を満たさない場合は、特定の二項演算、特定の関数本体、またはプロジェクト全体で暗黙的な拡張をオフにしてプロジェクトのコードを生成します。生成コードでの暗黙的な拡張の最適化を参照してください。

メモ

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

参考

|

関連するトピック