《程序设计优化.ppt》由会员分享,可在线阅读,更多相关《程序设计优化.ppt(29页珍藏版)》请在第壹文秘上搜索。
1、2023-3-30程序设计优化程序设计优化程序设计优化程序设计优化ARM C程序设计优化程序设计优化o编译器的特性编译器的特性o数据类型对程序效率的影响数据类型对程序效率的影响o循环方式对程序效率的影响循环方式对程序效率的影响o指针对程序效率的影响指针对程序效率的影响o边界对齐对程序的影响边界对齐对程序的影响程序设计优化一、编译器的特性一、编译器的特性void setzero(char *p, int n) for ( ; n0; n-) *p=0; p+; 清除从字符型指针清除从字符型指针p开始的开始的n个字节空间个字节空间程序设计优化编译器的特性编译器的特性(续续)void setzero
2、(char *p, int n) for ( ; n0; n-) *p=0; p+; 问题:问题:n编译器不知道编译器不知道n是否为是否为0。n编译器不知道编译器不知道p是否是否4字字节对齐。节对齐。n编译器不知道编译器不知道n是否为是否为4的倍数。的倍数。程序设计优化结论:结论:o编译器是保守的:编译器是保守的:n必须假定必须假定n的所有可能值。的所有可能值。n必须假定必须假定p所有可能的边界值。所有可能的边界值。程序设计优化编写高效编写高效C代码的要求代码的要求o了解哪些方面编译器是保守的了解哪些方面编译器是保守的o了解编译器对应的处理器体系结构了解编译器对应的处理器体系结构程序设计优化二
3、、数据类型对程序效率的影响二、数据类型对程序效率的影响 unsigned char i; for (i=0; i100; i+) oi声明为声明为unsigned char的优点的优点?n无符号字符变量表示的无符号字符变量表示的范围超过了范围超过了100,可以,可以完成题目要求。完成题目要求。nchar更节省寄存器和更节省寄存器和内存空间。内存空间。程序设计优化函数参数类型函数参数类型o总体思想:尽量采用总体思想:尽量采用int、long类型。类型。程序设计优化有符号数和无符号数有符号数和无符号数o如果程序中只有加、减、乘法,那么有符号如果程序中只有加、减、乘法,那么有符号数和无符号数的执行效
4、率没有区别。数和无符号数的执行效率没有区别。o如果有除法,那么需要额外的步骤。如果有除法,那么需要额外的步骤。程序设计优化有符号数和无符号数(续)有符号数和无符号数(续)有符号除法有符号除法 在在ARM C中,如果中,如果x是负数,那么除是负数,那么除2操作操作不是一个右移操作。例如不是一个右移操作。例如-3/2=-1。但是在。但是在ARM机器中:机器中:-3-2-1直直接接右右移移加加1右右移移程序设计优化结论:结论:o使用无符号数除法效率更高。使用无符号数除法效率更高。程序设计优化o对于存放在寄存器中的变量,尽量采用整型。对于存放在寄存器中的变量,尽量采用整型。o尽可能使用无符号数进行运算
5、。尽可能使用无符号数进行运算。o函数参数和返回值尽量采用整型数据。函数参数和返回值尽量采用整型数据。总结总结程序设计优化三、循环方式对程序效率的影响三、循环方式对程序效率的影响o循环是代码优化的重点循环是代码优化的重点oC程序主要使用程序主要使用for和和while进行循环进行循环程序设计优化固定次数的循环固定次数的循环o什么是什么是ARM上编写上编写for循环最高效的方法?循环最高效的方法?程序设计优化固定次数的循环(续)固定次数的循环(续) int i; for (i=0; i0; i-) o上面代码要实现转移上面代码要实现转移需要两条指令,首先需要两条指令,首先把某寄存器的内容和把某寄存
6、器的内容和100比较,其次条件比较,其次条件符合时转移。相同功符合时转移。相同功能的代码如果写作下能的代码如果写作下面形式,则可用面形式,则可用“BNE”一条指令实一条指令实现比较以及转移两个现比较以及转移两个功能。功能。程序设计优化至少一次循环至少一次循环o对于对于“for(;n0;n-)”,如果能确保第一,如果能确保第一次循环之前次循环之前n恒大于恒大于0,此时取消第一次,此时取消第一次n大大于于0的判断,是不会影响程序的逻辑,而且的判断,是不会影响程序的逻辑,而且显然程序执行效率可以提高,用显然程序执行效率可以提高,用dowhile循环可以达到这一目的循环可以达到这一目的程序设计优化循环
7、展开循环展开o循环开销重复循环开销重复100次,次,假设每次循环开销占用假设每次循环开销占用4个时钟周期,循环体个时钟周期,循环体中的加法占用中的加法占用1个时钟个时钟周期,那么有效程序仅周期,那么有效程序仅占占CPU执行时间的执行时间的20%,其余,其余80%都都是服务性开销,效率为是服务性开销,效率为1/5。 int i,t=0; for (i=100; i0; i-) t+; 程序设计优化循环展开循环展开(续续) int i,t=0; for (i=50; i0; i-) t+;t+; o每次循环开销每次循环开销4个时钟个时钟周期不变,但是有效程周期不变,但是有效程序占用序占用2个时钟周
8、期,个时钟周期,也即效率提高到也即效率提高到1/3。程序设计优化循环展开循环展开(续续)o问题:循环展开到什么程度?全部展开是否问题:循环展开到什么程度?全部展开是否最优?要意识到循环展开是有代价的:最优?要意识到循环展开是有代价的:n增加程序的长度。增加程序的长度。n循环体内代码越多,就越有可能造成循环体内代码越多,就越有可能造成cache失失效效o所以在任何程度上展开循环要具体问题具体所以在任何程度上展开循环要具体问题具体分析,在执行时间和代码量间找到一个最佳分析,在执行时间和代码量间找到一个最佳平衡点。平衡点。程序设计优化总结:总结:o循环计数递减。循环计数递减。o如确定循环次数大于如确
9、定循环次数大于1,那么用,那么用dowile。o对于小循环体,可以循环展开。对于小循环体,可以循环展开。程序设计优化四、指针对程序效率的影响四、指针对程序效率的影响o别名别名n当两个指针指向同一个对象时,这两个指针被当两个指针指向同一个对象时,这两个指针被称作该对象的别名。称作该对象的别名。o编译器的特点:编译器的特点:n不知道是否是别名不知道是否是别名n编译器是悲观的编译器是悲观的程序设计优化指针对程序效率的影响(续)指针对程序效率的影响(续)void throwtobag(int *mybag, int *yourbag, int *stone) *mybag += *stone;/语句1
10、 *yourbag += *stone;/语句2站在编译器的角度思考一下有无问题?站在编译器的角度思考一下有无问题?程序设计优化指针对程序效率的影响(续)指针对程序效率的影响(续)o上面代码的语句上面代码的语句1被被GCC编译时,会出现诸编译时,会出现诸如如“LDR ri,r2,#0”之类汇编指令,表之类汇编指令,表示首先要从示首先要从stone指向的地址读出一个数据,指向的地址读出一个数据,以便来把它加到以便来把它加到mybag指向指明的地址处。指向指明的地址处。此处此处r2代表代表stone,因为它是函数的第三,因为它是函数的第三个参数,轮到个参数,轮到r2来承载它。令人惊奇的是,来承载它
11、。令人惊奇的是,编译语句编译语句2时,仍然包含一条时,仍然包含一条“LDR ri, r2,#0”语句,语句,stone的值不是已经由语的值不是已经由语句句1得到了吗?得到了吗?为什么还要这一条语句?为什么还要这一条语句?程序设计优化指针对程序效率的影响(续)指针对程序效率的影响(续)o讨论:编译器不会自动识别指针指向的对象讨论:编译器不会自动识别指针指向的对象n不知道是否是别名不知道是否是别名n悲观、保守悲观、保守o思考:采用什么办法可以避免读两次内存?思考:采用什么办法可以避免读两次内存?程序设计优化五、边界对齐对程序的影响五、边界对齐对程序的影响o边界对齐问题边界对齐问题o_packed关
12、键字关键字程序设计优化边界对齐问题边界对齐问题o对齐问题对结构体也有影响。在结构体中定对齐问题对结构体也有影响。在结构体中定义若干变量如果长短相间,由于对齐问题,义若干变量如果长短相间,由于对齐问题,势必浪费一些空间。例如一个整形变量和一势必浪费一些空间。例如一个整形变量和一个字符变量放在一起,总共占用个字符变量放在一起,总共占用8个字节空个字节空间,但是其中保存有效数据的只有间,但是其中保存有效数据的只有5个字节。个字节。所以可以采用这种策略:所以可以采用这种策略:在结构体的最前面在结构体的最前面定义的所有的字符型变量,中间定义所有的定义的所有的字符型变量,中间定义所有的短整型变量,最后定义
13、所有的整形变量短整型变量,最后定义所有的整形变量,可,可以把浪费的空间减到最小。以把浪费的空间减到最小。程序设计优化_packed关键字关键字o有的有的C编译器支持编译器支持_packed关键字,它可关键字,它可以突破边界对齐的限制,在任意类型的变量以突破边界对齐的限制,在任意类型的变量按照任意顺序定义的情况下,都能够紧凑的按照任意顺序定义的情况下,都能够紧凑的安排存储空间,此时的代价是牺牲程序的运安排存储空间,此时的代价是牺牲程序的运行效率行效率程序设计优化_packed关键字(续)关键字(续)o代码完成从任意代码完成从任意地址地址p处读取一处读取一个整型变量,且个整型变量,且不要求此地址是不要求此地址是4的整数倍,返的整数倍,返回值为此地址起回值为此地址起始的始的4字节数据。字节数据。 int fetchint(_packed int *p) return *p; 程序设计优化_packed关键字(续)关键字(续)o上图是上述代码的实例,数据按照小端存储,上图是上述代码的实例,数据按照小端存储,读取一个没有对齐的整型数据。读取一个没有对齐的整型数据。