把优化等级调高后,程序反而慢了,Flash占用也增加了,这时很容易怀疑编译器出了问题。不过,Tasking的优化等级和速度、体积取舍是两个独立设置;内联、代码压缩以及链接布局,都可能改变结果。排查时可以保留一份原配置,每次只调整一项,再对照生成代码和板上测量值,找出变化发生的位置。
一、Tasking如何配置TriCore编译器优化选项
下面参照TASKING VX-toolset for TriCore 6.4r1的Eclipse界面,其他版本应核对对应手册。
1、选择构建配置与优化等级
①选中工程,点击【Project】→【Properties】→【C/C++Build】→【Settings】,在【Configuration】中选择待修改配置。
②打开【Tool Settings】→【C/C++Compiler】→【Optimization】,设置【Optimization level】。
③需要单独控制优化阶段时,选择【Custom optimization】,进入【Custom Optimization】调整具体选项。
预定义等级为0至3,分别对应No optimization、Optimize、Optimize more和Optimize most。等级2是该版本默认值;等级1较便于调试,等级3会启用更积极的优化,但不能据此保证每个函数都更快。
不要一开始就选择所有构建配置,否则用于对照的配置也可能一起被修改。
2、设置速度与体积取舍
①在【Optimization】页面找到【Trade-off between speed and size】,选择取舍值。
②打开【Global Options】,启用【Verbose mode of control program】,重新构建并查看实际调用参数。
取舍值0偏向速度,4偏向体积,中间值调整两者权重。它改变优化决策的倾向,不等同于优化等级,也不保证最终结果严格按某个比例变化。
例如固定等级2,仅比较取舍值0与4,就比同时调整等级、内联和链接选项更容易解释差异。还应核对文件、目录的单独设置,以及源码中的优化pragma是否覆盖了工程选项。
二、Tasking优化后执行时间或代码体积异常如何分析
先确定“异常”来自什么统计口径,再检查是哪项设置改变了代码。
1、用map核实实际空间占用
①进入【Project】→【Properties】→【C/C++Build】→【Settings】→【Tool Settings】→【Linker】→【Map File】,启用【Generate map file(.map)】。
②需要通过查看器分析时,启用【Generate XML map file format(.mapxml)for map file viewer】,加入内存使用、定位结果等信息。
③构建后打开前后两份map,对照代码段、常量段及地址分配。
ELF文件大小不能直接代表Flash占用,调试信息也会增大文件。比较体积时,应按相同口径查看实际分配的节区。若Flash增长,继续查哪些节区变大,是否增加了常量表、库函数或对齐填充。
2、检查内联与代码压缩
①返回【C/C++Compiler】→【Optimization】,查看【Inlining mode】及【Maximum size increment when inlining(in%)】。
②对照【Maximum size for functions to always inline】,检查内联阈值是否发生变化。
③在【Custom Optimization】中单独调整【Code compaction】,重新构建作对照。
内联减少调用开销,也可能把相同函数体复制到多个位置;代码压缩则可能提取重复指令,减小体积,同时引入额外调用。速度取舍值还会影响这些决策,不能把每次增长都归因于循环展开。
若只有一个模块明显变化,可在它的属性中检查单独设置,缩小调查范围。
3、核对执行时间的测量条件
①打开【Linker】→【Map File】,生成定位信息,对照热点函数的执行地址和所属存储区域。
②检查【Linker】→【Script File】中使用的【Linker script file(.lsl)】,确认两次构建采用相同布局规则。
测量时保持主频、输入、循环次数和中断条件一致,并区分首次运行与缓存预热后的耗时。函数地址移动、代码对齐或缓存行为改变,都可能影响速度,即使热点函数自身的指令没有明显变化。
时间突然缩短也要检查结果是否仍被使用,避免测量代码被优化掉。若运算结果同时变化,应先排查越界、未初始化数据及不恰当的硬件访问写法,再讨论性能。
三、Tasking优化配置怎样逐项验证并保留
找到可疑选项后,在相同输入和构建条件下复测,确认收益和代价都能重现。
1、拆开编译器与链接器变化
①在【C/C++Compiler】→【Optimization】中恢复对照设置,仅修改一个待验证选项。
②打开【Linker】→【Optimization】,核对链接优化是否与原配置一致。
③检查【Build for application wide optimizations(MIL linking)】,确认两次构建采用相同设置。
MIL应用级优化会扩大优化范围,不能把启用它后的结果,仅解释成普通等级变化。已有库也不会因为修改应用工程等级就自动按新参数重编。
2、对热点模块采用局部设置
①在工程树中右键热点源文件或目录,选择【Properties】→【C/C++Build】→【Settings】。
②进入【C/C++Compiler】→【Optimization】,仅对目标范围调整取舍值或内联设置。
局部调整后,既要测热点耗时,也要看整机任务周期和map变化。某个函数快了,可能只是把开销转移到调用者,或者增加了其他路径的取指压力。
3、保留实际构建参数
①打开【Global Options】,核对【Verbose mode of control program】。
②重新构建,在输出日志中检查目标文件的编译参数和最终链接参数。
保留工具链版本、配置、map及测试输入。工程属性只是设置入口,日志能帮助确认实际构建采用了什么,避免下一次切换配置后无法复现。
总结
优化配置值得保留的,是在实际任务中测得的收益,以及为此付出的空间代价。某次测试快了几个百分点,若只在特定输入或缓存状态下出现,还不足以作为长期配置依据。项目后续加入新功能、升级库或调整链接布局,原有结论也可能变化,留下可复测的输入和构建记录会省去不少查找时间。希望这些方法能帮到大家,遇到速度和体积变化时,能够找到具体原因,再决定哪些选项适合保留。如有相关需求,欢迎沟通咨询。