主要内容

生成启用隐式扩展的代码

隐式扩展指在应用按元素运算时自动更改兼容操作数的大小。对于两个维度中的每个维度,如果数组的维度大小相同或其中一个为单一维度,则这两个维度具有兼容的大小。请参阅基本运算的兼容数组大小

默认情况下,生成代码中的隐式扩展是启用的。启用隐式扩展生成的代码可能在以下方面不同于禁用隐式扩展生成的代码:

  • 输出大小

  • 其他代码生成

  • 性能变化

对于可变大小的动态数组,生成的代码展示这些变化以在运行时完成隐式扩展。

对于固定大小和常量数组,由于操作数的值和大小在编译时是已知的,因此为计算隐式扩展输出而生成的代码不需要其他代码生成,也不会导致性能变化。

要控制生成的代码中的隐式扩展,请参阅优化生成代码中的隐式扩展 (MATLAB Coder)

输出大小

隐式扩展自动扩展操作数以应用按元素运算。例如,假设有以下兼容大小的输入类型:

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

在启用隐式扩展的情况下,对这两个操作数执行二元运算会自动扩展 a_type 的第二个维度,从而产生 2×Inf 的输出大小。禁用隐式扩展时,a_type 的第二个维度不会自动扩展,输出大小为 2×1。

对于在生成的代码中禁用隐式扩展的情况下创建的现有工作流,为启用隐式扩展的相同 MATLAB® 代码生成代码可能会生成大小不匹配错误,或会更改二元运算和函数的输出大小。要对大小不匹配错误进行故障排除,请参阅解决错误:左侧是固定大小,而右侧是可变大小 (MATLAB Coder)

其他代码生成

如果操作数大小兼容,隐式扩展使操作数能够自动扩展。为了执行这种大小更改,生成的代码引入允许扩展操作数的代码。

以如下代码片段为例。函数 vector_sum 求两个数组之和。

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 + b 改为 out = a - b,则支持函数的名称将改为 minus

一些支持函数也可能命名为 expand_op,其中 op 指二元运算。在前面的示例中,如果将表达式 out = a + b 替换为 out = max(a,b),则生成的代码中支持函数的名称将改为 expand_max

如果一个表达式中的多项运算需要隐式扩展,生成的代码将包含名为 binary_expand_op 的支持函数。支持函数更改操作数的大小并应用二元运算。

如果您要应用特定二元运算和函数而不启用隐式扩展,请使用 coder.sameSizeBinaryOp (MATLAB Coder)。为应用此函数而生成的代码不包括用于扩展操作数的额外代码。此函数的输出不会扩展 MATLAB 中的操作数。此函数不支持标量扩展。操作数的大小必须相同。

如果您要在生成的代码中对函数内的所有二元运算禁用隐式扩展,请在所需的函数中调用 coder.noImplicitExpansionInFunction (MATLAB Coder)。MATLAB 代码中的隐式扩展仍处于启用状态。

性能变化

启用隐式扩展时生成的代码的性能可能与禁用隐式扩展时不同。根据使用隐式扩展的生成代码的输入,代码可能需要更长时间来计算输出。

如果由于隐式扩展,生成的代码不符合工作流的性能要求,请通过关闭特定二元运算、特定函数体或整个工程的隐式扩展来为工程生成代码。请参阅优化生成代码中的隐式扩展 (MATLAB Coder)

注意

在禁用隐式扩展之前,请确保外部代码不使用隐式扩展。如果您的工程包含来自外部源的 MATLAB 代码,则禁用整个工程的隐式扩展可能导致生成代码时出错。

另请参阅

(MATLAB Coder) | (MATLAB Coder)

主题