温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,汇文网负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。
网站客服:3074922707
编译
优化
等级
改变
造成
系统
问题
实验
探究
李佳佳
2023.7电脑编程技巧与维护1概述嵌入式系统具有体积小、成本低、运行稳定的特点,这些特点要求低功耗、快相应和系统稳定。因此嵌入式系统会采用小内存和可裁剪定制的系统,对开发者及其对时间和空间的把控能力发起了巨大的挑战。编译器性能优化能帮助嵌入式开发者减小代码量,同时提升程序执行效率,更好地满足嵌入式应用的性能要求1。无论是在企业应用中还是在学生学习过程中,优化等级一般设为22,这时程序代码量会大幅缩小,运行效率明显提升。但是当优化等级为2时,程序在运行时会出现一些问题。因此调整或者切换开发工具时,应时刻注意优化等级是否有变化,及时察觉并解决优化等级不同导致的问题。编译优化一般通过配置编译器优化等级来实现,此部分的知识比较抽象,学生难以理解,解决由此引起的问题更是无从着手。关于编译器优化造成的影响,没有现存可用的专门实验来展示,无论是学生还是在职工程师,都无法预先学习。因此,采用宏定义实现位带操作,设计此项操作展示优化等级改变所造成的影响的实验,引发学生对于优化等级改变所造成的问题的关注和思考。2编译器优化3编译器优化算法主要分为与机器有关的优化和与机器无关的优化两类。其中,用机器中执行更快、功能更强的指令替换原有指令的算法叫做与机器有关的优化4。调整代码结构的程序和元素,减少程序的执行时间和内存需求的优化技术叫做与机器无关的优化5。实验中主要来用与机器无关的优化算法,算法如下。2.1代数优化算法表达式替换、赋值传递、死变量删除、公用子表达式约减都属于代数优化算法6。2.2常量优化算法(1)常量合并算法。用常量运算结果替代程序中不必要的常量运算称为常量合并算法。常量合并算法常用于处理数组下标的优化和预处理常量的类型变化等7。常量合并算法如表1所示。(2)常量传递算法。用常量初值替代在整个变量生命周期中不修改值的变量。一般情况下,在常量传递优化后还可以进行常量合并8。常量传递算法如表2所示。2.3循环优化算法循环优化算法包括不变表达式外提、循环强度削减、循环变量约减、循环扩展、循环合并、循环嵌套次序调整9。2.4尾优化算法尾优化算法包括尾合并、尾循环10。此验证实验采用位带操作,实现STM32的GPIO读写操作,其中用到了常量优化的常量合并算法和常量传递优化算法,造成了程序优化后的错误问题。对程序中的循环结构及其他部分采用了循环优化等算法,从而使编译优化等级改变造成的系统问题的实验探究李佳佳,林喜文,张淑桐,范成名(青岛工程职业学院,山东 青岛266112)摘要:在嵌入式系统开发中,正确应用编译器优化等级提升嵌入式程序执行效率,同时缩小代码量,是嵌入式工程师的一项关键技能。为了在教学中讲解清楚优化等级带来的影响,引起学生对于此类问题的关注,设计了一项基于 STM32 芯片硬件环境和 MDK(Keil)软件环境的可观察的验证性实验。该实验根据嵌入式位带操作所控制的跑马灯程序在编译器 2 优化等级下引起的系统错误,展示较高等级代码优化造成的问题;采用易变型变量(volatile)关键字配合位带操作,解决较高优化等级代码的优化问题,为学生提供了查找、解决此类问题的有效方法。关键词:嵌入式;优化等级;易变型变量;STM32 芯片;位带操作源代码常量合并后#define MAXPACKETS 30#define PACKETSIZE 1024long maxstreamsize=(long)(MAXPACKETS*PACK-ETSIZE);float f=3.1+3.4;long maxstreamsize=30720L;float f=6.5;表1常量合并算法源代码经常量传递变形继续进行常量合并int x,y;int x,y;x=3;int x,y;x=3;x=3;y=x+5;y=3+5;y=8;表2常量传递算法48DOI:10.16184/prg.2023.07.0222023.7电脑编程技巧与维护整体的代码量大幅缩减,同时提升了程序的执行效率。3GCC 编译优化等级GCC编译器的优化级别11如表3所示。根据编译器优化等级的操作及说明,选用编译器优化等级0和优化等级2做对比实验,探究编译器无优化和最常用优化等级2之间的区别,观测优化后程序大小,运行效率的变化,同时展示优化等级改变后引发的问题,并提供一种解决方法。4验证实验4.1实验硬件电路实验采用硬件资源有STM32F103核心板一块,有按键1个、LED小灯8个。电路设计实验硬件。将LED小灯阴极接到STM32F103芯片的PB0-PB7引脚,将阳极经过一个100 限流电阻连接到5 V电源。一个按键KEY1一端接PA0,同时通过10 k电阻连接到5 V电源;另一端接地。实验硬件电路如图1所示。通过按键控制跑马灯程序的启动与停止。4.2实验软件代码设计根据实验硬件电路图,将LED灯阴极接到PB0-PB7,PB0-PB7并设置为输出模式。因此PB0-PB7输出低电平(0)时,控制相应LED小灯点亮;PB0-PB7输出高电平(1)时,控制相应LED小灯熄灭。根据实验硬件电路图,按下KEY1按键时,会产生低电平,抬起按键时,会产生高电平。PA0设置为输入模式,以获取按键的状态。KEY1按下时,跑马灯停止运行,所有LED小灯全部熄灭;KEY1抬起时,跑马灯启动。代码中按键的状态和小灯的控制,都是通过STM32的GPIO口操作进行。此处的GPIO操作经过位带操作来实现,以便提高代码的运行效率。程序的流程如图2所示。4.3实验过程(1)按照硬件电路图与控制逻辑,实现按键控制跑马灯的代码。注意GPIO控制采用位带操作来实现,并且位带操作不应用volatile关键字。代码如下。/用位带操作,内存映射,实现GPIO简化操作#define BITBAND(address,bit)(address&0 xF0000000)+0 x2000000+(address&0 xFFFFF)5)+(bit2)#define MEM_ADDR(address)*(unsigned long*)(address)#define BIT_ADDR(address,bit)MEM_ADDR(BITBAND(address,bit)/GPIO端口内存地址映射#define GPIOA_IDR_Addr(GPIOA_BASE+0 x08)/对IO口某一位操作,注意GPIOx端口仅16位,n的编号为0-15!#define PAin(n)BIT_ADDR(GPIOA_IDR_Addr,n)/PAx输入/跑马灯程序的一次循环,从全部熄灭到全部点亮,/然后从全部点亮到全部熄灭的代码。优化级别说明备注-O0关闭所有优化代码空间大,执行效率低-O1基本优化等级编译器在不花费太多编译时间的基础上,试图生成更快、更小的代码-O2O1的升级版,推荐的优化级别编译器试图提高代码性能,而不会增大程序体积和占用太多编译时间-O3最危险的优化等级会延长代码编译时间,生成更大体积、更耗内存的二进制文件,大大增加编译失败的几率和不可预知的程序行为,得不偿失表3GCC编译器的优化级别图1实验硬件电路图2程序流程开始GPIOx端口初始化否按键是否按下?是延时1 s执行跑马灯程序492023.7电脑编程技巧与维护Void pmd(void);/延时函数,采用软件延时Void Delay(unsigned int count)unsigned int i;for(;count!=0;count-)i=5000;While(i-);/用按键控制跑马灯的启动与停止逻辑while(1)/判断PA0引脚的电平If(Pain(0)=0)/跑马灯控制程序中应用寄存器编程,采用循环移位/操作,控制跑马灯程序pmd();elseDelay(100);(2)配置编译器优化等级为level-0,在编译过程中不会优化代码。将程序代码下载到硬件电路板上,进行测试,运行正常。(3)修改编译器优化等级为level-2,因此在编译过程中会优化代码,减小代码产生的执行文件的大小,同时优化程序的运行速度。将程序代码下载到硬件电路板上,进行测试,按键操作无任何响应。(4)修改位带操作,将其代码中宏定义添加volatile关键字,向编译器发出指令,不再优化volatile所在语句,仍然设置编译器优化等级为level-2,重新编译。将程序代码下载到硬件电路板上,进行测试。代码如下。#define MEM_ADDR(address)*(volatile un-signed long*)(address)(5)切换下载(2)和(4)中产生的可执行程序,观察跑马灯程序执行的速度差别。(6)查看(2)和(4)生成的可执行文件的大小,对比其差别。也可以通过查看两种优化等级的可执行文件的反汇编,查看汇编指令的数量,进而验证优化的效果。4.4实验现象及结论(1)执行结束之后,成功编写按键控制走马灯程序逻辑代码。(2)配置编译器优化等级为level-0,测试正常。下载好代码之后,LED跑马灯默认运行。按键按下,跑马灯关闭;按键抬起,跑马灯开启。如此循环。控制功能良好。(3)配置编译器优化等级为level-2,将程序代码下载到硬件电路板上,进行测试。LED跑马灯默认运行,按键操作无任何响应,即代码优化之后,跑马灯程序运行出现不能预知的错误。此错误是由编译器优化等级为level-2时进行常量优化造成的。由于位带操作应用宏定义,使PAin(0)表达式进行第一次读取寄存器值之后,将其作为常量,进行常量传递,继而对整个表达式应用常量合并算法,最终取得一个常量值。因此,每次判断PAin(0)数据都是常量1,无法获取到按键按下的真实状态值。于是,需要在宏定义中添加volatile关键字,向编译器发出指令,不要优化这段代码,每次都去寄存器读取新的值。(4)添加volatile关键字,命令编译器位带操作不做优化,将程序文件下载到硬件电路板后,进行测试。按键操作可正常控制跑马灯程序的启动与停止,即LED跑马灯默认运行。按键按下,跑马灯关闭;按键抬起,跑马灯开启。如此循环。控制功能良好。因此,volatile关键字的加入解决了编译器优化造成的程序异常。(5)切换代码,观察LED小灯顺序点亮的间隔,会发现优化等级为level-0时程序代码执行时间会比优化等级为level-2时程序代码执行时间的间隔长。由此确定编译器优化等级Level-2提升了程序的运行效率。(6)对比两个可执行文件的大小,优化等级为Lev-el-2的代码比优化等级为Level-1的代码少很多。对比两种优化等级生成的可执行文件的反汇编代码,查看汇编命令的变化。由此确定优化等级为level-2减少了代码量,节省了内存资源。通过此实验,提醒学生优化等级改变对于程序运行结果和效率会产生影响,并提出了有效的解决办法。5结语在嵌入式开发中,合理地管理有限的内存资源是十分必要的,通过调整编译器的优化等级减少代码量、提升执行效率成为嵌入式工程师的一项重要技能。基于STM32硬件开发板,以嵌入式开发为实验应用背景,对编译器优化等级进行实验讲解,同时警示学生优化等级改变会引起不可预知的问题,通过实验提供优化等级切换所引起编译问题的解决方案。同时以更加直观的方式让学生观测编译等级提升带来的优化效果,并掌握解决(下转第81页)502023.7电脑编程技巧与维护由于编译器优化所造成的问题的能力,完成此部分知识的强化学习。参考文献1赵明.嵌入式技术现状及趋势发展研究J.电脑与电信应用技术与研究,2020(8):68-70.2韩冬瑞,刘拥军,马青松.基于嵌入式多智能系统的工业无线传感器网络性能分析J.信息记录材料,2022,23(8):29-31.3钟卫,吴雨.C编译中的优化技术分析J.计算机研究与发展,1992(12):26-32.4吴元彬.C语言程序的理解与编译优化J.现代计算机,2020(18):93-96.5RANDAL E.BRYANT,DAVID R.OHalloran.深入理解计算机系统M.3版.龚奕利,贺莲,译.北京:机械工业出版社,2019.6刘铭.编译原理M.4版.北京