3. 模型的代码优化方法
文章目录:
3.1 代码优化概述
3.2 代码优化度量标准
3.3 代码优化方法设置
3.3.1 数据初始化
3.3.2 终止代码
3.3.3 整型数据的溢出回环
3.3.4 代数运算异常保护代码
3.3.5 无效的模块
3.3.6 优化变量的使用形式
3.1 代码优化概述
在生成代码时,对模型设置不同的配置选项,会对模型生成的代码产生不同的影响,评价代码优化情况,需要基于以下几个维度思考:
- 调试性(Debugging)
- 可追踪性(Traceability)
- 执行效率(Efficiency)
- 安全预防(Safety precaution)
调试性
指的是调试模型生成代码的编译过程可追踪性
指的是模型和代码之间的映射关系是否易于追踪执行效率
包括生成的代码所占用的RAM、ROM空间大小,以及处理器执行生成代码的效率,这一般是我们最关心的优化目标安全预防
指的是代码是否具备防止执行错误的情况发生,例如:除零检查、溢出检查等。安全预防一般与效率是矛盾的,因为安全检查需要消耗存储空间和执行时间
3.2 代码优化度量标准
- 在生成代码时,可以配置生层静态代码的度量报告:
static code metric
,报告详细列举了代码量的信息,例如:文件数量
、代码行数
、全局变量
、入口函数
等信息 - 选择不同的代码优化配置选项,生成的代码量是不一样的,通过对比某一优化选项开启和关闭时,代码度量报告的区别,即可了解该优化选项的效果;当然也可以直接对比生成的代码,查看该优化选项的具体作用
- 打开静态代码度量报告的方法如下所示:
- 选择
static code metric
选项后,生成代码的报告会有个统计页,可以查看生成代码的相关信息
3.3 代码优化方法设置
3.3.1 数据初始化
- 对于浮点数的零初始化过程,可以配置使用
memset()
函数,或者直接var=0.0
赋值,初始化的数据非常多时,前者会花费更多的存储空间和执行时间 - 初始化还可以通过:
remove initialization code
选择移除零初始化代码,因为一般变量的内存区域初始值已经为零,不需要再初始化,这种配置是最高效的
3.3.2 终止代码
- 如果终止代码中没有必要代码,通过设置:
removing termination code
,用来把变量的中止赋值等代码优化掉
3.3.3 整型数据的溢出回环
- 在数值类型转换计算时,会存在数据溢出情况
例如:将浮点数float 80000.0转换为16位无符号整型数据unsigned short,很显然这里发生了数据溢出,因为16位无符号整型数据最大值为65535;在C语言中,溢出的位会被忽略,只保留低16位数据,float 80000.0转换为16位无符号整型数据的结果为unsigned short 14464
- 在Simulink中,常会使用
数据转换模型
来实现数值转换,有些配置选项会添加软件处理过程,来保证这个过程的正确性
/* Model step function */
void float2int_step(void)
{
real_T tmp;
/* DataTypeConversion: '<Root>/Data Type Conversion' incorporates:
* Constant: '<Root>/Constant'
*/
tmp = fmod(floor(float2int_P.Constant_Value), 65536.0);
/* Outport: '<Root>/y' incorporates:
* DataTypeConversion: '<Root>/Data Type Conversion'
*/
float2int_Y.y = (int16_T)(tmp < 0.0 ? (int32_T)(int16_T)-(int16_T)(uint16_T)
-tmp : (int32_T)(int16_T)(uint16_T)tmp);
}
- 一个简单的数据类型转换,被生成了多个操作,这部分的代码是不必要的,去掉的方式如下
- 配置移除数据回环代配置选项后,生成的代码如下:
/* Model step function */
void float2int_step(void)
{
/* Outport: '<Root>/y' incorporates:
* Constant: '<Root>/Constant'
* DataTypeConversion: '<Root>/Data Type Conversion'
*/
float2int_Y.y = (int16_T)floor(float2int_P.Constant_Value);
}