matlab coder 对生成代码进行优化
为了改进生成代码的执行速度和内存使用量,matlab® coder™ 引入了以下优化:
常量折叠
代码生成器会尽可能计算 matlab 代码中仅包含编译时常量的表达式。在生成的代码中,它用计算结果替换这些表达式。此行为称为常量折叠。由于使用了常量折叠,生成的代码不必在执行期间计算常量。
以下示例说明在代码生成过程中经过常量折叠的 matlab 代码。函数 multiplyconstant
将矩阵中的每个元素乘以一个标量常量。该函数使用三个编译时常量 a
、b
和 c
的乘积来计算该常量。
function out=multiplyconstant(in) %#codegen a=pi^4; b=1/factorial(4); c=exp(-1); out=in.*(a*b*c); end
代码生成器计算涉及编译时常量 a
、b
和 c
的表达式。它用生成代码中的计算结果替换这些表达式。
当表达式只涉及标量时,可能会发生常量折叠。要在其他情况下显式强制实施表达式的常量折叠,请使用 函数。有关详细信息,请参阅。
控制常量折叠
您可以从命令行或工程设置对话框中控制可进行常量折叠的指令的最大数量。
在命令行中,为代码生成创建一个配置对象。将属性
constantfoldingtimeout
设置为所需的值。cfg=coder.config('lib'); cfg.constantfoldingtimeout = 200;
使用 app,在工程设置对话框中的 all settings 选项卡上,将字段 constant folding timeout 设置为所需的值。
循环融合
代码生成器会尽可能将具有相同运行次数的连续循环融合到生成代码中的单个循环中。这种优化可减少循环开销。
以下代码包含连续循环,这些循环会在代码生成过程中融合。函数 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 代码中的不可达过程。例如,如果 语句的某个分支不可达,则不会为该分支生成代码。
以下示例包含不可达代码,这些代码在代码生成过程中会被排除。函数 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
if
、elseif
、else
语句的第二个分支不可达。如果变量 x
大于 10,显然它也大于 0。因此,会优先于第二个分支执行第一个分支。
matlab coder 不会为不可达的第二个分支生成代码。
memcpy
调用
为了优化用于复制连续数组元素的生成代码,代码生成器会尝试通过调用 memcpy
来替换代码。memcpy
调用的效率可能高于 for
循环或多个连续元素赋值等代码的效率。
请参阅。
memset
调用
为了优化对连续数组元素进行字面常量赋值的生成代码,代码生成器会尝试通过调用 memset
来替换代码。memset
调用的效率可能高于 for
循环或多个连续元素赋值等代码的效率。
请参阅。