Main Content

MATLAB Coder 对生成代码进行优化

为了改进生成代码的执行速度和内存使用量,MATLAB® Coder™ 引入了以下优化:

常量折叠

代码生成器会尽可能计算 MATLAB 代码中仅包含编译时常量的表达式。在生成的代码中,它用计算结果替换这些表达式。此行为称为常量折叠。由于使用了常量折叠,生成的代码不必在执行期间计算常量。

以下示例说明在代码生成过程中经过常量折叠的 MATLAB 代码。函数 MultiplyConstant 将矩阵中的每个元素乘以一个标量常量。该函数使用三个编译时常量 abc 的乘积来计算该常量。

function out=MultiplyConstant(in) %#codegen
 a=pi^4;
 b=1/factorial(4);
 c=exp(-1);
 out=in.*(a*b*c);
end

代码生成器计算涉及编译时常量 abc 的表达式。它用生成代码中的计算结果替换这些表达式。

当表达式只涉及标量时,可能会发生常量折叠。要在其他情况下显式强制实施表达式的常量折叠,请使用 coder.const 函数。有关详细信息,请参阅Fold Function Calls into Constants

控制常量折叠

您可以从命令行或工程设置对话框中控制可进行常量折叠的指令的最大数量。

  • 在命令行中,为代码生成创建一个配置对象。将属性 ConstantFoldingTimeout 设置为所需的值。

    cfg=coder.config('lib');
    cfg.ConstantFoldingTimeout = 200;
  • 使用 App,在工程设置对话框中的所有设置选项卡上,将字段常量折叠超时设置为所需的值。

循环融合

代码生成器会尽可能将具有相同运行次数的连续循环融合到生成代码中的单个循环中。这种优化可减少循环开销。

以下代码包含连续循环,这些循环会在代码生成过程中融合。函数 SumAndProduct 计算数组 Arr 中元素的和与乘积。该函数使用两个单独的循环来计算 y_f_sum 和与 y_f_prod 乘积。

function [y_f_sum,y_f_prod] = SumAndProduct(Arr) %#codegen
  y_f_sum = 0;
  y_f_prod = 1;
  for i = 1:length(Arr)
     y_f_sum = y_f_sum+Arr(i);
  end
  for i = 1:length(Arr)
     y_f_prod = y_f_prod*Arr(i);
  end

从该 MATLAB 代码生成的代码在单一循环中计算和与乘积。

合并的连续矩阵运算

代码生成器会尽可能将 MATLAB 代码中的连续矩阵运算转换为生成代码中的单一循环运算。这种优化可减少在单独的循环中执行矩阵运算所涉及的过多循环开销。

以下示例包含发生连续矩阵运算的代码。函数 ManipulateMatrix 将矩阵 Mat 中的每个元素与一个 factor 相乘。然后,该函数为结果中的每个元素加一个 shift

function Res=ManipulateMatrix(Mat,factor,shift)
  Res=Mat*factor;
  Res=Res+shift;
end

生成的代码将乘法和加法合并到单个循环运算中。

排除不可达代码

代码生成器会尽可能在代码生成中隐藏 MATLAB 代码中的不可达过程。例如,如果 if, elseif, else 语句的某个分支不可达,则不会为该分支生成代码。

以下示例包含不可达代码,这些代码在代码生成过程中会被排除。函数 SaturateValue 根据其输入 x 的范围返回一个值。

function y_b = SaturateValue(x) %#codegen
  if x>0
    y_b = x;
  elseif x>10 %This is redundant
    y_b = 10;
  else
    y_b = -x;
 end

ifelseifelse 语句的第二个分支不可达。如果变量 x 大于 10,显然它也大于 0。因此,会优先于第二个分支执行第一个分支。

MATLAB Coder 不会为不可达的第二个分支生成代码。

memcpy 调用

为了优化用于复制连续数组元素的生成代码,代码生成器会尝试通过调用 memcpy 来替换代码。memcpy 调用的效率可能高于 for 循环或多个连续元素赋值等代码的效率。

请参阅memcpy 优化

memset 调用

为了优化对连续数组元素进行字面常量赋值的生成代码,代码生成器会尝试通过调用 memset 来替换代码。memset 调用的效率可能高于 for 循环或多个连续元素赋值等代码的效率。

请参阅memset Optimization