首页> 中国专利> 一种能量受限嵌入式系统的算法源程序节能优化方法

一种能量受限嵌入式系统的算法源程序节能优化方法

摘要

本发明公开了一种能量受限嵌入式系统的算法源程序节能优化方法,本方法主要针对诸如无线传感器网络节点、移动终端、便携式设备等能量受限的嵌入式系统的算法源程序进行节能优化。该方法基于系统具有的资源条件,在不改变算法的前提下,针对影响算法运行过程能耗的源程序的五个构成要素,即数据存储与访问方式、分支结构、循环结构、函数调用和条件判断,通过改变数据存储与访问方式、基于概率调整语句顺序、减少隐含附加指令、以增加程序的存储空间开销来缩减执行时间这四种机制,进行减少算法源程序执行过程所消耗能量的编程优化,降低原有源程序的运行能量代价,从而达到降低系统运行能耗、延长工作时间的目的。

著录项

  • 公开/公告号CN103760965A

    专利类型发明专利

  • 公开/公告日2014-04-30

    原文格式PDF

  • 申请/专利权人 中南大学;

    申请/专利号CN201410059981.7

  • 申请日2014-02-21

  • 分类号G06F1/32;

  • 代理机构长沙市融智专利事务所;

  • 代理人欧阳迪奇

  • 地址 410083 湖南省长沙市岳麓区麓山南路932号

  • 入库时间 2024-02-19 23:32:30

法律信息

  • 法律状态公告日

    法律状态信息

    法律状态

  • 2020-02-11

    未缴年费专利权终止 IPC(主分类):G06F1/32 授权公告日:20160817 终止日期:20190221 申请日:20140221

    专利权的终止

  • 2016-08-17

    授权

    授权

  • 2014-06-04

    实质审查的生效 IPC(主分类):G06F1/32 申请日:20140221

    实质审查的生效

  • 2014-04-30

    公开

    公开

说明书

技术领域

本发明技术涉及嵌入式系统的算法源程序优化领域,特别涉及无线传感器网络节点、移动便携式终端、穿戴式设备等能量供给有限或不连续的系统和场合的能量受限嵌入式系统的算法源程序节能优化方法。

背景技术

近年来,嵌入式系统已经成为电子信息产业中最具增长力的一个分支。随着半导体工艺技术的发展,微处理器的晶体管集成度及时钟频率在不断提高,性能增强的同时功耗也急剧增加,处理器的功耗问题已成为制约处理器发展的一个重要瓶颈。其中部分嵌入式系统因为需要满足可移动性或便携性,设备或系统均采用有限容量的电池供电,系统的能量供应受到限制,使得此类嵌入式设备的功耗问题尤为突出。因此,如何降低系统能耗,充分利用有限的能源,成为能量受限嵌入式系统设计过程中必须解决的问题。

能量是功率在时间上的累积,功耗仅能反应某个时刻系统的能量消耗大小,但能量消耗的总量还与运行的时间有关,因此,对于能量供给受限系统,能耗的表述更为贴切,在降低系统能耗的问题上,也可从降低运行功耗和减少运行时间两个角度来考虑解决方案。

在实现低能耗的问题上,早期研究者普遍关注硬件途径的改进方法,主要通过降低硬件的功耗来节约能量。由于受到当前技术及工艺水平的限制,单纯的硬件层次的方法无法有效的降低系统能耗。随着嵌入式操作系统的发展,软件对嵌入式系统的管理、功能实现起到重要作用。嵌入式系统越来越庞大,算法复杂度越来越高,软件层次能耗优化技术的意义也就越加凸显。虽然功耗最终由硬件系统产生,但影响功耗的因素不只是硬件本身,还有控制或指挥硬件操作运行的软件。大量研究表明,在硬件相同的条件下,软件层次的能耗优化技术对降低系统能耗具有良好效果,软件层次的能耗优化成为降低系统能耗的一个关键环节。

当前软件层次的能耗优化技术大致可分为两类,一类是与硬件结合的软件管理方法,例如动态电源管理(DPM)以及动态电压调节(DVS)等;另一类是以降低能量消耗为目标的软件优化策略,例如,编译优化、源程序优化以及算法优化等。软件管理方式通过调节系统资源能有效减少系统的能量消耗,但是对系统运行特性的调整必须根据系统性能需要,因而具有一定局限性;而软件的优化方式是降低程序本身的运行能量代价,在任何运行条件下对降低系统能耗都是有意义的。

当前许多研究与实验结果表明,不同的汇编指令、源程序、软件算法都会使得硬件工作方式不同,从而对系统的功耗带来不同影响。有关软件层次能耗优化方法的研究从底层到上层也大致可分为:

(1)编译级优化:面向源程序的编译过程,对编译器进行优化,注重指令的调整,指令优化调度,存储分配等;

(2)源程序级优化:面向算法的实现过程,注重编程中语句的调整、数据存储形式的选择,减少源程序的运行代价;

(3)算法级优化:面向任务或事件,注重算法的选择,算法复杂度的降低;

目前,相关研究大多侧重于编译级和算法级。基于能量考虑的编译优化可以减小代码运行的能耗,但此优化只能针对已有代码,并不能改变源程序,其优化空间受到限制。算法级的优化能明显改善算法的复杂度及运行性能,是降低软件运行能耗的重要途径,但在算法实现过程中的源程序却在很大程度受限于编程者的主观性,不同编程者编写代码的质量差异很大,因而存在很大的优化空间。

源程序级的优化(即实现算法的源程序代码的编写优化)的意义在于,在编译环境一定、原有算不变的条件下对软件进行优化。源程序优化介于编译优化和算法优化之间,能有效弥补二者的不足,虽然不改变编译器的编译过程,但可以引导编译器编译出高效的代码;虽然不改变原有算法,但可以改变算法的实现过程,降低软件运行的能耗。

此外,随着编译技术的成熟,编译器的效率的不断提高,为了加快软件的开发速度,高级语言已成为嵌入式系统的主流开发环境,编译器将源程序与机器指令隔开,编程者不再关注代码在底层如何编译实现,加快了软件的开发速度,同时也将效率优化的任务转移给编译器。尽管高级语言相对于汇编语言的代码效率差异已经在逐步缩小,但当程序规模变大、复杂度变高,而主频不能无限提高且电源容量有限时,高级语言的效率问题也就凸显出来。因此,在依靠高效编译器的同时还需结合适当的编程方法以及源程序的编程优化方法。

以往对于源程序的优化都只限于为编程者提供建议。随着源程序的优化重要性的提升,尤其是在资源受限,特别是能量供给受限的环境下,源程序的优化方法备受关注。除了遵循编程规范和优化建议外,还可以通过对源程序的编程改进或调整达到优化效果,但目前研究都只涉及源程序的某个方面,对优化的对象考虑不全,提出方法也较单一,缺乏一个全面的、系统的方法。

嵌入式系统所采用的微处理器/单片机系统有一个共同的特点,即程序存储器的容量往往远大于数据存储器的容量,而内部寄存器更是少之又少。尽管微处理器在硬件上也在不断改进,程序存储器容量不断增大,但数据存储器(RAM)的容量和内部寄存器数量却变化很小,资源相对短缺。依靠编译器去分配有限资源、调整指令是降低代码运行代价的主要途径。此外,通过改变数据的存储方式来减少数据的访问代价,根据源程序已知特性调整源程序语句顺序来减少执行的语句,通过牺牲一定的程序存储空间来减少源程序的运行时间等源程序层次的优化方法也是降低能耗的有效途径。

对于嵌入式系统底层程序的开发,由于C语言较高的运行效率及较好的移植性,C语言成为了使用最为广泛的一种高级语言。因此,针对C语言的算法源程序级能耗优化方法的研究具有重要意义和实用价值。

发明内容

本发明的目的是提出一种用于能量受限的嵌入式系统的算法源程序级能耗优化方法,采用本发明,能有效降低系统的软件运行的能耗,有效延长设备的使用周期,提升设备续航能力。

为了实现上述技术目的,本发明的技术方案是,一种能量受限嵌入式系统的算法源程序节能优化方法,包括以下步骤:

步骤一:在系统所给资源条件或系统分配给具体程序的有限的程序与数据存储空间的基础上,对算法源程序进行分析,选取程序中涉及数据存储与访问、选择结构、循环结构、函数调用、条件判断的部分,并进行优化对象判断以找出需要和可以进行优化的对象;

其中数据存储与访问部分的优化对象为需重复访问的以非局部变量定义的数据或采用非寄存器寻址方式的数据;

选择结构部分的优化对象为分支选中概率已知或可预测,且未按分支选中概率设计分支顺序的选择结构,或概率未知但具有四分支以上分支的选择结构;

循环结构部分的优化对象为关系成立概率已知或可预测,且未按关系成立概率设置判断顺序的条件判断,或概率未知但未按关系表达式运算复杂程度设置判断顺序的条件判断;

循环结构部分的优化对象为可以减少循环过程中用于循环控制的隐含附加指令的循环结构;

函数调用部分的优化对象为可以减少函数调用过程中用于数据保护和程序转移的隐含附加指令的函数;

步骤二:对步骤一中所选择出的优化对象进行优化以提高程序运行效率来达到节能的目的;

其中数据存储与访问部分优化对象的优化方法为通过更改数据的访问方式或存储形式来减少数据访问过程所需要的指令周期数;

选择结构部分优化对象的优化方法为按分支选中的概率改变分支顺序,或对分支进行分段,从而减少分支选择过程中进行判断的次数;

条件判断部分优化对象的优化方法为根据关系成立概率,或根据关系表达式复杂程度调整关系表达式的判断顺序,从而提高条件判断的效率;

循环结构部分优化对象的优化方法为改变循环的计数方式、展开循环体、调整循环嵌套方式,从而减少循环结构中隐含附加指令;

函数调用部分优化对象的优化方法为通过函数的展开和用全局变量替代公共的函数参数,来减少函数调用过程中的隐含附加指令;

步骤三:对算法源程序再次执行步骤一,若找出需要进行优化的对象则继续执行步骤二和步骤三,若不再具备优化对象或者实施优化所需的存储空间需求已超出系统分配的资源,则结束整个优化过程。

所述的方法,所述的数据存储与访问部分的优化对象包括:局部的数组数据,即以局部变量形式声明在函数内部的数组数据,非寄存器寻址方式的数据即在函数内部重复访问的但并非局部变量的常量、全局变量、数组数据、结构体数据和使用下标引用的数组数据;所述的优化方法为:将局部数组声明为静态,即在静态存储区的剩余容量容许条件下将定义在函数内部的数组声明为静态,利用临时局部变量处理非寄存器寻址方式的数据,即把非寄存器寻址方式的数据转移到临时局部变量之中,使数据的处理在寄存器中完成,之后将数据返回原来的非局部变量中,用指针方式访问数组数据,即建立临时指针变量指向数组,用指针方式替换下标方式访问数组数据。

所述的方法,所述的选择结构部分的优化对象包括:未按分支选中概率设置分支顺序的if…else语句,即高概率分支位于if…else语句后一分支的分支结构,未按分支选中概率设置分支顺序的多分支选择结构,即高概率分支位于靠后部分的多分支选择结构,四个以上分支的多分支选择结构;所述的优化方法为:按分支选中概率调整if…else语句分支的顺序,即将条件判断语句逻辑关系取反使后一分支提前,按分支选中概率对switch语句进行转换和分支顺序调整,即将switch语句转换成if…else语句后按概率大小由高到低调整分支顺序,对选择结构分支进行分段后再进行分支选择,即利用关系语句先将包含四个以上分支的选择结构进行分段,在各段中再进行分支选择。

所述的方法,所述的条件判断部分优化对象包括:多关系表达式逻辑“与”的条件判断语句,即关系运算结果为“假”概率大的关系表达式位于语句中靠后位置的条件判断语句,多关系表达式逻辑“或”的条件判断语句,即关系运算结果为“真”概率大的关系表达式位于语句中靠后位置的条件判断语句,未按关系表达式运算复杂程度设计判断顺序的条件判断语句,即运算复杂程度高的关系表达式位于语句中靠前位置的条件判断语句;所述的优化方法为:按关系成立概率调整含有二个以上的条件“与”的条件判断顺序,即将含二个以上关系“与”的语句中的逻辑“假”概率大的关系语句提前,按关系成立概率调整含有二个以上条件“或”的条件判断顺序,即将含二个以上关系“或”的语句中的逻辑“真”概率大的关系语句提前,按关系表达式复杂程度调整条件判断顺序,即将运算代价大的关系运算语句置后。

所述的方法,所述的循环结构部分优化对象包括:单纯的“增计数”控制方式的循环结构,即使用“增计数”方式且循环控制变量与循环体无关的循环,已知循环次数的循环结构,即循环体的循环次数已知或循环次数的倍数关系已知的循环结构,外循环次数大于内循环次数的嵌套循环;所述的优化方法为:改变循环的计数方式,即将单纯的“增计数”控制方式变换成“减计数”的方式,展开循环体,即不改变实际需要的循环操作,在程序存储空间有余量条件下,将循环展开成顺序结构,改变循环嵌套的方式,即将“大循环套小循环”这种外层循环的次数大于内层循环的次数的嵌套方式变换成“小循环套大循环”即外层循环次数小于内层循环次数的嵌套方式。

所述的方法,所述的函数调用部分优化对象包括:函数或循环中的函数调用,即在循环结构内部或在函数内部调用的函数,多个函数之间共用的函数参数;所述的优化方法为:展开循环内部或函数内部的函数,即将循环内部或函数内部调用的函数展开,使该部分程序流程变换为顺序执行方式,对简单函数直接用宏定义替代函数调用,用全局变量替代公共的函数参数,即把公共的函数参数改换成静态存储的全局变量。

所述的方法,所述的算法源程序为使用C语言编写的程序。

本发明的技术构思为:针对给定的系统硬件环境,结合C语言的特点和编译方法,以及已有的优化经验和方法,从程序的五个重要构成要素对源程序进行分析,并选定源程序中需要优化的各个对象,进而在系统资源允许的前提下对给定优化对象进行优化,然后重新对优化后的源程序进行构成分析并优化,直至不具可优化对象或者实施优化所需的存储空间需求已超出系统分配的资源。从而使算法的运行能耗能有效降低。此优化方法包含的具体步骤为:

步骤1:系统环境的分析

对源程序的优化是在一定环境下进行的,运行源程序的硬件条件不同,其优化效果也将不同;同理,对源程序进行编译的编译环境不同,优化效果也会存在差异。此外,系统资源条件还决定了能否对优化对象实施优化。因此,在进行优化之前还需确定实施优化的硬件环境和编译环境,其中主要是明确系统中可以为该源程序所用或为其分配的程序存储空间大小和数据存储空间大小。

一般算法源程序(C语言)的构成基本包括了数据存储与访问、分支结构、循环结构、函数调用、条件判断等环节或要素。按以下步骤2到步骤6,分5个环节对源程序进行进一步分析,并从可选的优化对象中确定出需要优化的对象。

步骤2:源程序中“数据存储与访问”部分的分析及优化对象的确定

C语言中数据可分为变量和常量,按作用域不同可分为局部和全局变量,局部变量按照存储形式不同又可分为自动变量、静态变量和寄存器变量;相同数据类型的数据可以组织成数组,不同类型数据可以组织成结构体。数据的不同数据类型和组织形式对应不同的数据格式,将很大程度地决定程序的执行效率及相应的能耗水平。因此,数据的存储与访问方式需要优化,以降低这一环节的源程序的运行能耗。

优化对象选择原则:将重复访问的非局部变量数据或采用非寄存器寻址方式的数据选作优化的对象。

1)局部的数组数据

当数组在函数外部申明时,数组数据存储于全局的静态存储区;当数组数据在函数内部申明时,数组数据在堆栈之中临时存储,函数调用完后即释放。而访问堆栈区数据的能量代价高于访问静态区数据的代价。因此,可以对源程序中出现的局部数组数据的存储形式进行调整,以减少数据访问的代价。

2)非寄存器寻址方式的数据

函数内部除局部变量外,还存在采用非寄存器寻址方式访问的数据,例如常量、全局变量、数组数据、结构体数据、表达式结果等,相对于优先使用寄存器的局部变量,它们的能量消耗要高。非寄存器寻址方式的数据出现在循环结构中或在函数内部重复出现时,数据的重复访问也会使源程序的执行效率降低。因此,可以对源程序中出现在循环中且采用非寄存器寻址方式的数据的访问方式进行调整,减少数据访问代价。

3)使用下标引用的数组数据

数组数据的访问有使用下标访问和指针访问两种方式,利用下标访问数组时,编译器需要根据数组首地址和下标计算得到地址,而指针访问时,指针本身即为地址,数据读写更加高效,能量消耗更小。因此,需要对源程序中使用下标访问的数组数据的访问方式进行调整,减少数据访问的代价。

步骤3:源程序中“选择结构”部分的分析及优化对象的确定

与顺序结构不同,选择结构需要根据一定条件判断决定程序的走向。C语言有两种选择语句,即if语句实现的两个分支的选择和switch语句实现的多个分支的选择。选择结构会根据条件判断的结果对分支进行选择,由于条件判断的先后顺序使得选择各个分支的效率是不一样的,因此,选择结构中分支的顺序将影响选择结构的执行效率及能耗水平,因此,对选择结构进行优化,能提高选择的效率。

优化对象选择原则:将分支选中概率已知或可预测,且未按分支选中概率设计分支顺序的选择结构,或概率未知但具有四分支以上分支的选择结构选作优化的对象。

1)未按分支概率设计分支顺序if…else语句

选择结构中if语句执行时,根据条件判断结果进行分支选择,结果为“真”即执行if之后语句,结果为“假”,程序需要跳转至else之后。相比于前者的“判断-执行”方式,后者的“判断-跳转-执行”方式处理代价更高。当if语句的前后两分支出现概率不一样,概率高分支出现在else之后时的运行能量消耗比出现在if之后的分支要高。因此,需要对源程序中分支概率已知或可预计,且未按概率安排分支顺序的if语句的分支顺序进行调整,以减少条件判断的次数。

2)未按分支选中概率设置分支顺序的多分支选择结构。

多分支的选择结构与if语句类似,各个分支的执行代价并不相等,分支越靠后,需要的“判断-跳转”次数越多,相应的执行能量消耗越高,概率高的分支出现在多分支结构的前部时的运行能量消耗比出现在多分支后部的要低。因此,需要对源程序中分支概率已知或可预计、且未按概率安排分支顺序的多分支选择结构进行分支顺序调整,减少条件判断的次数。

3)四个以上分支的多分支选择结构。

在分支选中概率未知或概率相差不大、且分支数较多的选择结构中,选择后半部分分支的能耗高于选择前半部分分支的能耗。因此,需要对源程序中分支选中概率未知或概率相差不大、且分支数目较多的选择结构进行顺序调整,减少对位置居后的分支的选中率。

步骤4:源程序中“条件判断”部分的分析及优化对象的确定

条件判断语句一般出现在if语句、while语句、for语句等语句中,根据C语言的语法规则,当条件判断语句为多关系的“与”运算时,一旦“与”运算符之前的关系语句的运算结果为“假”,将结束该条件判断,也即不进行运算符之后的运算操作;当判断语句为多关系的“或”运算时,一旦“或”运算符之前的关系语句运算结果为“真”,将结束该条件判断。关系表达式运行的顺序将影响判断的效率,因此,需要对条件判断进行优化,减少判断的次数,提高判断的效率。

优化对象选择原则:将关系成立概率已知或可预测、且未按关系成立概率设置判断顺序的条件判断,或概率未知但未按关系表达式运算复杂程度设置判断顺序的条件判断选作优化对象。

1)多关系表达式逻辑“与”的条件判断语句。

多关系“与”的条件判断语句中,若条件判断语句中出现结果为“假”的关系表达式,将结束该判断。如果先对关系运算结果为“假”概率较大的关系表达式进行判断,则所需进行的关系运算次数少。因此,需要对源程序中各关系运算表达式成立的概率已知,且关系运算结果为“假”概率大的关系表达式位于语句中靠后位置的条件判断语句进行调整,减少条件判断中所需进行关系运算次数。

2)多关系表达式逻辑“或”的条件判断语句。

多关系“或”的条件判断语句中,若条件判断语句中出现结果为“真”的关系表达式将结束该判断。如果先判断关系运算结果为“真”概率较大的关系表达式,则所需进行关系运算次数更少。因此,需要对源程序中各关系运算表达式成立的概率已知,且关系运算结果为“真”概率大的关系表达式位于语句中靠后位置的条件判断语句进行调整,减少条件判断中所需进行关系运算次数。

3)未按关系表达式运算复杂程度设计判断顺序的条件判断。

在执行条件判断语句的过程中,位置越靠前的关系表达式被执行的次数越多,若靠前的关系表达式运算复杂,则整个条件判断语句的执行效率就低。因此,需要对源程序中各关系运算表达式的运算复杂程度已知、且未按复杂程度设计判断顺序的条件判断进行顺序调整。

步骤5:源程序中“循环结构”部分的分析及优化对象的确定

循环结构用来解决程序中需要重复处理的问题。C语言中有三种循环语句:for语句、while语句和do…while语句。循环结构在实现过程中,除了重复执行需要执行的语句外,还要执行条件判断、程序跳转等一些对循环进行控制的隐含指令,循环次数越多,所需执行的隐含附加指令就越多,能耗代价就越大,因此,需要对循环结构进行优化,减少隐含的附加指令。

优化对象选择原则:将可以减少循环过程中用于循环控制的隐含附加指令的循环结构选作优化的对象。

1)单纯的“增计数”控制方式的循环结构

循环结构中有一类循环,单纯的利用循环使目标代码运行一定次数,且计数控制的变量与函数体中变量无关。计数控制的方式又可以分为增计数和减计数两种,增计数方式即从初始值增加到目标次数时停止增加,减计数方式即从初始值减少到目标值时停止减少。二者效率的差异主要来自比较的方式,判断两数据大小在编译时实际上会转换成判断二者差值与0的比较,而与0比较无需求差时,效率较高。因此,需要对源程序中使用增量计数方式的循序进行调整,减少条件判断代价。

2)已知循环次数的循环结构

循环结构中,循环次数越多,循环控制部分带来的附加操作就越多,在完成需要次数的操作外增加了额外的能量消耗。源程序中循环体需重复的次数一般即为循环体执行的次数,当循环次数已知时,可以在一次循环中执行多次循环体,使得循环体执行的次数小于循环重复的次数,源程序执行的能耗也就因附加指令的减少而降低。因此,需要对源程序中已知循环次数的循环结构进行源程序调整,减少循环体的循环次数。

3)外循环次数大于内循环次数的嵌套循环

对于循环嵌套结构,当外部循环次数大于内部循环次数时,这种循环结构的附加指令数比外部循环次数小于内部循环次数的循环附加指令数多,因而前一种情况的源程序执行时的能量消耗也相应较高。因此,需要对源程序中外循环次数大于内循环次数的嵌套方式进行调整,以减少循环的附加指令。

步骤6:源程序中“函数调用”部分的分析及优化对象的确定

函数的调用意味着程序的跳转,为确保程序能返回并正确续接先前执行的过程,返回地址及寄存器先前存储的数据必须先保存,待返回时再恢复寄存器的数据。相比于顺序执行,函数调用增加了地址及数据保存与还原的隐含附加指令,当函数被频繁调用时,这些附加操作部分的消耗就明显增加。因此,需要对函数调用进行优化,减少隐含附加指令。

优化对象选择原则:将可以减少函数调用过程中用于数据保护和程序转移的隐含附加指令的函数作为优化的对象。

1)函数或循环中的函数调用

当函数调用出现在顺序结构中,函数仅会被调用一次或少数次;而当函数调用出现在循环结构或函数中,调用次数将明显大于前一情况。函数的频繁调用带来程序的频繁跳转,将额外增加源程序的运行能耗。因此,需要对源程序中函数或循环中的函数调用进行源程序的调整,减少程序跳转带来的隐含附加指令。

2)多个函数之间共用的函数参数

函数传递的参数在编译时会作为局部变量处理,将优先占用寄存器,参数越多,需要占用的寄存器越多,加上函数内部定义的局部变量,程序跳转时需要保存与还原的数据将增多,能耗也随之增大。另外由于函数参数本身是程序模块化设计的基础,不能对所有的函数参数进行优化。因此,需要对源程序中传递参数较多的函数的参数多个函数共同包含的公共函数参数进行调整,减少函数传递的参数。

步骤7:优化对象判断

由以上步骤2到步骤6对源程序的主要构成成分进行分析,确定出需要进行优化的对象,再根据步骤1分析所得系统资源情况,确定出能够进行优化的对象后,若存在这样的优化对象且具有实施优化的剩余资源或存储空间,以下按步骤8到步骤12完成上述优化对象的优化,否则,结束优化过程。

步骤8:源程序中“数据存储与访问”部分的优化

优化原则:通过更改访问数据的访问方式或存储形式,减少数据访问过程中的能量消耗。针对步骤2确定的需要优化对象分别给出优化的具体方法如下。

1)将局部数组声明为静态

访问静态存储区数据的能耗代价小于访问堆栈中的数据,根据系统的RAM中的静态存储区容量,将定义在函数内部的数组声明为静态,减少访问局部数组数据的能量消耗。但静态存储区的容许空间不足时不能进行存储形式的调整。

2)利用临时局部变量处理非寄存器寻址数据

对于重复访问且能耗代价高的非寄存器寻址方式的数据,声明临时的局部变量,将非寄存器寻址方式数据转移到寄存器中,使数据的处理在寄存器中完成,处理完之后将数据返回原有数据中,减少数据处理的能量消耗

3)用指针方式访问数组数据

因指针方式访问数组比数组下标访问方式更高效,因此,建立临时指针变量指向数组,用指针方式替换下标方式对数组数据的访问,提高数组数据的访问的效率,降低源程序运行能耗。

步骤9:源程序中“选择结构”部分的优化

优化原则:根据分支选中概率改变分支的顺序,或对分支进行分段,减少分支选择过程中进行判断的次数。针对步骤3确定的待优化对象分别给出具体优化方法如下:

1)按分支选中概率调整if…else语句分支的顺序

if语句的执行效率与分支选中的概率和分支的顺序有关,当已知概率或可预计时,调整if语句判断方式,将条件判断语句逻辑关系取反,使后一分支提前,减少不必要的跳转,可提高执行效率,减低源程序运行能耗。

2)按分支选中概率调整多分支选择结构的分支顺序

多分支选择结构执行的效率同样与分支别选中的概率和分支的顺序有关。switch语句的多分支选择结构在编译时,会按case后的值(选择某分支的条件值)从小到大排列,调整case的顺序(分支的顺序)不会改变编译结果,优化时,将switch语句转换成if…else语句,用if…else语句的嵌套形式实现多分支的选择,按概率大小由高到低调整分支顺序,减少对大概率分支的判断次数。

3)选择结构分支的分段。

当选择结构包含的分支过多,且分支被选中概率未知,优化时,可利用关系语句先将分支分段,各段再进行分支选择,可提高整体执行效率。

步骤10:源程序中“条件判断”部分的优化

优化原则:根据关系成立概率或根据关系表达式复杂程度调整表达式的判断顺序,提高条件判断的效率。针对步骤4确定的待优化对象分别给出优化的具体方法如下:

1)按关系成立概率调整多条件“与”的条件判断顺序

多条件判断的中各关系表达式的顺序将影响判断的效率,将多关系“与”的语句中的逻辑“假”概率大的关系语句提前,可减少判断。

2)按关系成立概率调整多条件“或”的条件判断顺序。

多条件判断的中各关系表达式的顺序将影响判断的效率,将多关系“或”的语句值的逻辑“真”概率大的关系语句提前,可减少判断。

3)按关系表达式复杂程度调整条件判断顺序

多条件判断中复杂程度高的关系运算表达式的位置将影响判断的效率,将运算代价大的关系运算语句置后,提高条件判断的效率。

步骤11:源程序中“循环结构”部分的优化

优化原则:通过改变循环的计数方式、展开循环体、调整循环嵌套方式,减少循环结构中的隐含附加指令。针对步骤5确定的需要优化对象分别给出优化的具体方法如下:

1)改变循环的计数方式

“减计数”方式的条件判断部分所需指令相比“增计数”方式更少,将“增计数”的计数控制方式替换成“减计数”的方式,减少了条件判断表达式的所需的指令,使程序效率提高,降低了源程序运行的能量消耗。

2)展开循环体

循环次数将决定循环结构隐含附加指令的多少,在不改变实际需要的循环操作的情况下将循环适当展开,减少附加指令,从而减少总的指令周期数。此外,循环只能展开成循环次数的因数次。

3)改变循环嵌套的方式

循环的嵌套方式也将影响循环结构附加指令的多少,将“大循环套小循环”嵌套方式的循环替换成“小循环套大循环”的方式,减少循环的附加指令,降低源程序运行的能量消耗。

步骤12:源程序中“函数调用”部分的优化

优化原则:通过函数的展开和减少函数的参数,来减少函数调用过程中的隐含附加指令。针对步骤6确定的需要优化对象分别给出优化的具体方法如下:

1)展开循环内部或函数内部的函数

函数频繁的调用将带来程序指针的大量修改及中间数据的保存,将循环内部或函数内部调用的函数展开,尽量使程序流程保持为顺序执行方式,减少程序的分支跳转,这样将显著地减少能量消耗。另外,对于简单的函数直接利用宏定义替代函数调用,避免程序的跳转,减少源程序运行的能量消耗。

2)用全局变量替代公共的函数参数

参数数目越多,需要保存和还原的数据就可能越多,进行优化时,在可能的情况下应尽量减少传递参数的数目,用静态存储全局变量的参数替代多个函数共同包含的公共函数参数,减少源程序运行的能量消耗。

步骤13:重复步骤2到步骤12,即权利要求1中的“步骤一、步骤二”的过程

对于已完成以上优化的算法源程序,原有源程序已经改变。因此,重新根据系统的资源容许条件,针对新的源程序按步骤2到步骤6进行构成分析,重新确定优化对象,然后按步骤8到步骤12对源程序进行再次优化,直到无优化对象或者实施优化所需存储空间已超出系统分配的资源为止。

本发明的技术效果在于,根据本发明的编程优化方法对算法的源程序进行编程优化,能明显减少源程序运行所需的指令周期,提高算法的执行效率,降低算法执行的能量消耗,延长设备的使用周期,普遍适用于不同应用需求的能量受限的嵌入式系统。

本发明提供的算法源程序能耗优化方法,不仅可以提高算法的运行的能耗,还能有效提高算法执行效率以及算法的实时性。同时本发明部分优化方法可供其他高级语言借鉴。

附图说明

图1为本发明的流程图。

具体实施方式

以下结合具体实施例对本发明做进一步详细说明。

实施例1:哈夫曼编码算法源程序

本实例所选算法为主要用于数据压缩的静态霍夫曼编码经典算法,具体面向具有无线通信功能的能量受限平台,如无线传感器网络等的无损数据压缩需要。

哈夫曼编码(Huffman Coding)是一种编码方式,是可变字长编码的一种。该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,实现对数据的压缩。压缩算法实现过程的源程序如下:

依据本发明方法,实现编程优化的具体应用步骤如下:

步骤1:系统环境的分析

实例中的算法源程序均由C语言编写,所采用编译环境为IAR Workbench for MSP430v5.50,硬件环境为MSP430F2618,该微控制器是16位RISC架构微处理器,具有116KB Flash及8KB RAM,16个内部寄存器,12个为通用寄存器。

测试所用算法为经典的静态霍夫曼编码,对单次长度为1KB的数据进行压缩,加上输出编码,及解压缩的编码需要3KB RAM,此外编码过程还需要建立频度统计表、节点信息表、编码表大概4KB RAM,硬件资源满足算法需求,算法流程简单,规模较小,对实时性要求不高。

步骤2:源程序中“数据存储与访问”部分的分析及优化对象的确定

1)局部的数组数据。在频度统计函数FrequencyCount内部声明记录频度数据的数组Cnt[MAXLEAF],此外在压缩函数HuffmanCoding内部声明了用于保存节点信息和编码表的结构体数组HuffNode[MAXNODE]和HuffCode[MAXLEAF],编译时将被分配到堆栈之中,程序运行代价高,以上数据存储形式不合适,需要优化,确定为待优化对象1。

2)非寄存器寻址方式的数据。数组数据Cnt[i]、pSrc[i],指针的间接引用的数据*nDesLen,结构体数据code[value].length、node[i].data、code[value].code、code[value].length都非寄存器寻址方式,而且这些数据需要重复访问,具有很高的访问代价,以上数据访问方式不合适,需要优化。确定为待优化对象2。

3)使用下标引用的数组数据。数组pDes、pSrc、Cnt、node分别是存储输入数据、输出输出数据、频度数据和节点数据,是压缩算法实现过程中关键的部分,有大量数据需要对数组进行读写,而都采用访问代价较高下标引用的方式访问数组数据,以上数组的访问方式不合适,需要优化。确定为待优化对象3。

步骤3:源程序中“选择结构”部分的分析及优化对象的确定

1)未按分支概率设计分支顺序if…else语句。if语句if(CurLength>=8)用来对判断当前编码的长度,当编码长度大于等于8bit时,输出编码,长度小于8bit时继续对下一数据进行编码,由哈弗曼的编码机制可以,算法出现概率越高的数据编码越短,因此,CurLength小于8的概率更大,以上if语句的判断方式不合适,需要优化。确定为待优化对象4。

2)未按分支概率设计分支顺序的多分支选择结构。本例不含多分支选择结构,无此项优化对象。

3)分支数较多的多分支选择结构。本例不含多分支选择结构,无此项优化对象。

步骤4:源程序中“条件判断”部分的分析及优化对象的确定

1)多关系表达式逻辑“与”的条件判断语句。在寻找当前节点中最小频度节点函数FineMinLeaf中存在多关系条件判断表达式if(pNode->weight<pMinNode->weight&&pNode->parent==0),但关系运算pNode->weight<pNode1->weight与关系运算pNode->parent==0的成立的概率不确定,因此,此项不能选作优化对象。

2)多关系表达式逻辑“或”的条件判断语句。本算法源程序不包含多关系表达式逻辑“或”的条件判断语句,本例无此项优化对象。

3)未按关系表达式运算复杂程度设计判断顺序的条件判断。条件判断表达式if(pNode->weight<pMinNode->weight&&pNode->parent==0)中,关系运算pNode->weight<pNode1->weight的复杂程度远高于关系运算pNode->parent==0。造成条件判断代价过大,需要进行优化。确定为待优化对象5。

步骤5:源程序中“循环结构”部分的分析及优化对象的确定

1)单纯的“增计数”控制方式的循环结构。本算法源程序中无单纯用于计数控制的循环体,循环体和循环控制变量相关,因此无此项优化对象。

2)已知循环次数的循环结构。本算法源程序中存在3组循环次数确定的循环结构for(i=0;i<nSrcLen;i++,src++),for(i=0;i<MAXLEAF;i++),for(i=0;i<nSrcLen;i++),由于nSrcLen、MAXLEAF已知且能进行分解,可进行优化。确定为待优化对象6。

3)外循环次数大于内循环次数的嵌套循环。本算法源程序中的循环嵌套方式都是算法实现需要的,都不具备方式的转变,因此本例无此项优化对象。

步骤6:源程序中“函数调用”部分的分析及优化对象的确定

1)函数或循环中的函数调用。本算法源程序中,寻找当前最小频度节点函数FineMinLeaf(node,num)在创建哈夫曼树的函数CreatHuffTree中频繁被调用,调用次数为2倍leaf,将使程序频繁跳转,需要进行优化。确定为待优化对象7。

2)传递参数较多的函数。本算法源程序中参数pSrc(原始数据指针),nSrcLen(原始数据长度),pDes(压缩数据指针),nDesLen(压缩数据长度)这四个参数被多个函数传递,需要进行优化。确定为待优化对象8。

步骤7:优化对象判断

通过以上步骤2到步骤6确定出了需要优化的具体对象1~8,结合步骤1对系统资源的分析可知,系统资源满足优化要求,能够进行优化。

步骤8:源程序中“数据分配”部分的优化

1)将局部数组声明为静态。(优化对象1)

2)利用临时局部变量处理非寄存器寻址数据。(优化对象2)

3)用指针方式访问数组数据。(优化对象3)

步骤9:源程序中“选择结构”部分的优化

1)按概率调整if…else语句分支的顺序。(优化对象4)

2)按概率对switch语句进行转换和分支顺序调整。本例无此项优化对象。

3)选择结构分支的分段。本例无此项优化对象。

步骤10:源程序中“条件判断”部分的优化

1)按概率调整多条件“与”的条件判断顺序。本例无此项优化对象。

2)按概率调整多条件“或”的条件判断顺序。本例无此项优化对象。

3)按关系表达式复杂程度调整条件判断顺序。(优化对象8)

优化前①if(pNode->weight<pNode1->weight&&pNode->parent==0)优化后①if(pNode->parent==0&&pNode->weight<pNode1->weight)

步骤11:源程序中“循环结构”部分的优化

1)改变循环的计数方式。本例无此项优化对象。

2)循环体的展开。(优化对象5)

3)循环嵌套方式改变。本例无此项优化对象。

步骤12:源程序中“函数调用”部分的优化

1)展开循环内部或函数内部的函数。(优化对象6)

2)用全局变量代替公共的函数参数。(优化对象7)

步骤13:重复从步骤2到步骤12

回到步骤2到7,在进行完一轮优化后步骤4中可选对象1成为优化对象。

1)改变计数控制方式。(优化对象9)

完成第二轮优化后源程序不具备优化可能,停止优化。优化后的源程序如下。

以上实施过程对给定的算法源程序,从五个方面对源程序做了9项优化。为体现对源程序优化带来的节能效果,实例中的优化收益均用能量收益(J)表示。由能量公式E=U×i×t可知,在系统电压一定的情况下,能量消耗电流消耗和运行时间有关。各指令的电流消耗情况虽然各不一样,但相互之间差异并不大,为方便计算,选取活动模式下的平均电流消耗水平(515uA),运行的时钟频率选取为1MHz。此时由源程序优化所得的指令周期减少量ΔN,可得能量收益为:

ΔE=UI·Δt=3.3×515×10-6×10-6×ΔN=1.7ΔN(nJ)

综合的优化效果、能量的收益情况如下:

情形1:对1KB波动较小的数据进行一次压缩。算法压缩率为26.56%。

情形2:对1KB波动较大的数据进行一次压缩,算法压缩率为16.01%

由于本发明提出的优化方法是针对源程序的全局性的方法,不一定所提的各项优化方法在任一个算法源程序的优化中都有需要或者都是同时适用。在实施例1的优化过程中已使用了所提的14项方法中的9项,其中未使用的5项方法是:调整多条件“与”和多条件“或”的条件判断顺序、循环嵌套方式改变、对switch语句的转换与分支顺序调整和选择结构分支的分段。为说明本发明中上述实施例1中未使用的5项的有效性,它们将通过以下实施例2和3分别体现。

实施例2:已知某年几个特定节日为星期几,计算后续多年中每年这些节日是星期几。

源程序中CalculateHolidayOfDuration是在已知YearStart年HolidayNum个特定节日的星期情况后,计算此后duration年该节日为星期几的函数。源程序如下:

步骤1:系统环境的分析

实例中的算法源程序均由C语言编写,所采用编译环境为IAR Workbench for MSP430v5.50,硬件环境为MSP430F2618,该微控制器是16位RISC架构微处理器,具有116KB Flash及8KB RAM,16个内部寄存器,12个为通用寄存器。

测试时,假设已知2013的5月1号、7月1号、8月1号、10月1号分别为星期三、星期一、星期四、星期二,利用CalculateHolidayOfDuration函数计算出此后100年(2014-2113)在该节日的星期情况,计算过程中结果需要占用404B的静态RAM,闰年情况需要占用100B的静态RAM,硬件资源满足算法需求,算法流程简单,规模较小。

步骤2:源程序中“数据存储与访问”部分的分析及优化对象的确定

1)局部的数组数据。本例无此项优化对象。

2)非寄存器寻址方式的数据。本例无此项优化对象。

3)使用下标引用的数组数据。本例无此项优化对象。

步骤3:源程序中“选择结构”部分的分析及优化对象的确定

1)未按分支概率设计分支顺序if…else语句。本例无此项优化对象。

2)未按分支概率设计分支顺序的多分支选择结构。本例无此项优化对象。

3)分支数较多的多分支选择结构。本例无此项优化对象。

步骤4:源程序中“条件判断”部分的分析及优化对象的确定

1)多关系表达式逻辑“与”的条件判断语句。源程序中闰年判断语句存在多关系表达式逻辑“与”的条件判断语句year%100!=0&&year%4==0,可知后关系表达式year%4==0为“假”的概率要远大于前关系表达式year%100!=0,需要进行优化,确定优化对象1。

2)多关系表达式逻辑“或”的条件判断语句。源程序中闰年判断语句存在多关系表达式逻辑“或”的条件判断语句year%400==0||(year%100!=0&&year%4==0),可知后关系表达式year%100!=0&&year%4==0为“真”的概率远大于前关系表达式year%400==0,需要进行优化,确定优化对象2。

3)未按关系表达式运算复杂程度设计判断顺序的条件判断。本例无此项优化对象。

步骤5:源程序中“循环结构”部分的分析及优化对象的确定

1)单纯的“增计数”控制方式的循环结构。本例无此项优化对象。

2)已知循环次数的循环结构。本例无此项优化对象。

3)外循环次数大于内循环次数的嵌套循环。源程序中for(int i=HOLIDAY_NUM-1;i>=0;i--)循环内部存在for(int index=0;index<duration;index++)循环,且外循环次数远大于内循环次数,需要进行优化,确定优化对象3。

步骤6:源程序中“函数调用”部分的分析及优化对象的确定

1)函数或循环中的函数调用。本例无此项优化对象。

2)传递参数较多的函数。本例无此项优化对象。

步骤7:优化对象判断

通过以上步骤2到步骤6确定出了需要优化的具体对象1~3,结合步骤1对系统资源的分析可知,系统资源满足优化要求,能够进行优化。

步骤8:源程序中“数据分配”部分的优化。本例无此项。

步骤9:源程序中“选择结构”部分的优化。本例无此项。

步骤10:源程序中“条件判断”部分的优化

1)按概率调整多条件“与”的条件判断顺序。(优化对象1)

优化前year%100!=0&&year%4==0优化后year%4==0&&year%100!=0

2)按概率调整多条件“或”的条件判断顺序。(优化对象2)

优化前year%400==0||(year%4==0&&year%100!=0)优化后(year%4==0&&year%100!=0)||year%400==0

3)按关系表达式复杂程度调整条件判断顺序。本例无此项优化对象。

步骤11:源程序中“循环结构”部分的优化

1)改变循环的计数方式。本例无此项优化对象。

2)循环体的展开。本例无此项优化对象。

3)循环嵌套方式改变。(优化对象3)

步骤12:源程序中“函数调用”部分的优化。本例无此项。

步骤13:重复从步骤2到步骤12

回到步骤2到7,不再具备优化对象,结束优化过程。优化后的源程序如下。

本例从5个方面考察了源程序,选定并进行了3项优化,即多个条件中“与”判断顺序和“或”的判断顺序的调整、循环嵌套方式改变(大外层小内层改换为小外层大内层)。为有效体现这3项的效果,其他项中有的(如减计数循环控制方法)在未进行本例的优化前就已采用了。根据实施例1的能量收益计算方法,本例获得的优化效果如下:

实施例3:多分支选择源程序实例

除了对涉及多分支的“选择结构”的优化外,本发明所提的所有其他项优化方法的有效性在实施例1和2中均已体现,本实施例用以说明对多分支“选择结构”进行按概率对switch语句的转换和分支顺序调整和对选择结构分支的分段处理这两项优化方法的有效性。

1)按分支选中概率调整多分支选择结构的分支顺序

现利用数组Arr1的元素模拟8个分支的序号进行分支的选择,假设Arr1元素出现概率已知,Arr1[50]={8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,7,7,7,7,7,7,7,7,7,7,6,6,6,6,6,6,6,5,5,5,5,5,4,4,4,4,3,3,2,1};可知分支概率由高到低依次是8,7,6,5,4,3,2,1,因此,优化时选择结构也按概率高低顺序调整原有分支顺序。多分支结构可以由switch语句和if…else嵌套实现,优化前后指令周期数如下:

由上可见,优化前,由switch语句实现和由if…else嵌套实现的多分支选择的指令周期数相差不大,而按概率优化多分支选择的顺序之后,if…else嵌套实现的多分支选择的指令周期明显减少,而由switch语句实现的多分支选择指令周期不变,因此,利用if…else嵌套实现的多分支调整分支顺序,有利于提高分支选择的效率。

2)多分支选择结构分支的分段

现同样利用数组Arr2的元素模拟8个分支的序号进行分支的选择,假设Arr2元素概率相等,Arr2[40]={8,8,8,8,8,7,7,7,7,7,6,6,6,6,6,5,5,5,5,5,4,4,4,4,4,3,3,3,3,3,2,2,2,2,2,1,1,1,1,1};可知各个分支出现的概率相当,因此,优化时利用条件判断对选择结构进行分段,然后在分段中再进行多分支选择,优化前后指令周期数如下。

由上可见,优化前,由switch语句实现和由if…else嵌套实现的多分支选择的指令周期数相差不大。在对多分支进行分段后,两种方式实现的多分支选择的指令周期都有减少,而由if…else嵌套实现的多分支选择的减少更加明显,因此,利用条件判断对多分支进行分段,有利于提高分支选择的效率。

下面对循环嵌套方式改变所产生的效果作出介绍:

循环结构每循环一次执行的语句实际包含两部分,一是源程序需要重复执行的语句,二是隐含的循环控制语句,对于多层循环嵌套的语句结构,循环嵌套方法不同带来的执行效率差异来自与循环语句隐含的循环控制指令,假设循环语句中每次循环所执行的隐含控制指令周期数均为Nctrl,内、外循环次数分别为m和n,源程序需要重复执行语句的指令周期数为Nsrc,则整个嵌套循环需要执行的指令周期数Ncyc

Ncyc=n×(m×(Nsrc+Nctrl)+Nctrl)

将上式展开可得:

Ncyc=nmNsrc+nNctrl(m+1)

可见,式中nmNsrc才是源程序中按算法进行操作运算所需要的指令周期数,而nNctrl(m+1)则是由循环控制带来的附加隐含指令的周期数。

为了说明嵌套方式对循环结构执行效率的影响,将上式变换为:

Ncyc=nm×(Nsrc+Nctrl)+nNctrl

可见Ncyc由外循环次数决定。若将内、外嵌套次数m与n交换,改变的只是由外循环次数决定的隐含控制指令周期数,也即nNctrl将变换成mNctrl。因此,将“大循环套小循环”的嵌套方式变换成“小循环套大循环”的方式,由m<n可知,减少了循环过程所执行的隐含附加指令。

去获取专利,查看全文>

相似文献

  • 专利
  • 中文文献
  • 外文文献
获取专利

客服邮箱:kefu@zhangqiaokeyan.com

京公网安备:11010802029741号 ICP备案号:京ICP备15016152号-6 六维联合信息科技 (北京) 有限公司©版权所有
  • 客服微信

  • 服务号