主要内容

优化生成代码中的隐式扩展

默认情况下,生成代码中的隐式扩展是启用的。代码生成器在生成的代码中引入修改以执行隐式扩展。生成的代码中的更改可能导致额外的代码来扩展操作数。操作数的扩展可能会影响生成代码的性能。请参阅生成启用隐式扩展的代码 (MATLAB Coder)

隐式扩展可能会更改支持的运算符和函数的输出大小,从而导致工作流中出现大小和类型不匹配错误。

要精细地控制在生成的代码中何处启用隐式扩展,请在您的 MATLAB® 代码中使用以下函数:

以如下代码片段为例。函数 vector_sum 求两个大小兼容的数组之和。

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 的生成代码中的变化,分别包含禁用和启用隐式扩展的情况。为了生成代码,操作数 ab 的类型定义为:

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 提供的操作数的大小必须相同。

在工程中禁用隐式扩展

隐式扩展默认启用。如果您不需要在生成的代码中使用隐式扩展,可以禁用启用隐式扩展 (MATLAB Coder)配置参数。您也可以在代码配置对象中将 EnableImplicitExpansion 属性设置为 false

通过将模型范围的参数在 MATLAB 函数中启用隐式扩展设置为 false,在 Simulink® 模型中禁用隐式扩展。也可以使用以下命令:

set_param(gcs,'EnableImplicitExpansion',false);

注意

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

另请参阅

(MATLAB Coder) | (MATLAB Coder)

主题