软件优化技术

软件优化是一项系统工程。要理解软件优化,首先对软件要有个本质的认识。软件是什么呢?它是一组在计算机平台上运行的逻辑代码。这个概念比较拗口。第一,软件是一组计算机能理解并运行的逻辑代码。第二,软件一定是运行在某个计算机平台上,可能是大型机,可能是PC,可能是手机。好,认识了这两点。就可以正确认识软件优化。

首先,软件既然是计算机的逻辑,那么好的软件就是贴合计算机体系结构的逻辑,贴合的程度越高,软件的性能越好。现代计算机,从大型机到手机,其体系结构都体现出一个基本的原理:局部性原理。80%的计算机资源(CPU,内存……)是花费在20%的代码上的。Cache技术就是这个原理的集中体现,无论是硬件(如CPUcache)还是软件(如操作系统的working set),都是尽可能的重用“计算”,这样就提高了整个计算机系统的性能。局部性原理在软件优化上有两个外延。第一,去优化消耗80%计算机资源的20%的代码,而不是去优化消耗20%计算机资源的80%的代码。第二,在优化重要的20%代码时,无论是数据结构还是算法,都要尽量使其贴合局部性原理。经常使用的数据结构应该尽量紧凑,使其符合空间局部化,这样就可以最大限度的利用CPUdata cache。算法应当尽量重用计算,使其符合时间局部化。当然,算法和数据结构不是孤立的,在局部性原理指导下,二者的密切协作对软件性能是起决定性作用的。

其次,软件是运行在某个平台上,那就要充分利用该平台的特性去做优化。如果说局部性原理是个“泛化”的原则,那么平台优化就是“特化”技术了。各种平台的差别很大,所以所用的技术当然会有所不同。PC的内存和手机的内存不是一个数量级的,当然对数据结构和算法都要有不同的设计;超线程的CPU,双内核CPU都对优化提出不同要求;CPU的流水线结构不同,对汇编指令的调整也就不同;有的CPUSIMD指令,当然可以充分利用。另外,这里的“平台”除了指硬件(CPU体系和内存体系),还包括系统软件,特别是操作系统和编译器。要清楚,我们的软件是在操作系统的调度下与硬件资源打交道的,所以要清楚操作系统的特性(如它是如何管理进程/线程,如何调度页面,页面大小是多少)。编译器是软件的代言人,我们用高级语言写的程序只是程序员逻辑,经过编译器这一中间层,未必能贴合CPU逻辑,所以要了解不同编译器的特性,使程序逻辑尽量贴合编译器思维,这样能生成更高效的代码。总而言之,既然要在某个平台上做优化,就要对该平台有深入的认识,包括硬件(CPU体系和内存体系)和系统软件(操作系统和编译器)。

以上两点就是软件优化的基础。脱离了这个基础,优化就将成为空中楼阁。

 

软件优化是一项系统工程。总体而言,整个优化框架可以分为两个部分:设计优化和代码优化。

1,设计优化

       设计优化包括了软件体系结构的优化,数据结构的优化,算法的优化。

1.1       软件体系结构的优化

软件优化首先要对整个软件体系结构有个清晰的了解。在认识了整个软件的目标功能后,围绕这个目标,软件的模块划分,软件的运行流程都要一清二楚。整个软件的“数据流”和“控制流”都要能在头脑中清晰的呈现出来。各个模块的接口和各个模块的数据结构间的关系,都要有清晰的认识。在这个基础上,才能对各个模块做数据结构的优化和算法的优化。

1.2       数据结构的优化

数据结构的设计是个大学问。基本上,数据结构是为算法服务的,所以要根据算法来确定数据结构。但也有几个我认为比较通用的原则。

第一,   除非算法有特殊的需要,否则尽量用紧凑性好的数据结构,如数组。

第二,   根据空间局部性原理,尽量紧凑经常访问的数据,合理选择数组结构和结构数组。

第三,   如果数组比较大,其元素的尺寸应尽可能小,如可以用char就不要用short。除此以外,不要吝惜内存,尽量用int作为数据类型。

第四,   如果CPU具有SIMD指令,则第三点要重新考虑,根据算法需要,合理安排

数组元素的尺寸。

1.3       算法的优化

算法的优化可以分为两种:算法设计的优化和算法实现的优化。

1.3.1          算法设计的优化

算法设计的优化是指对求解的问题提出更具效率的求解思路。好的算法设计对软件性能具有决定性影响。例如Video Encodermotion vector的搜索算法有很多,选择合适的算法是很重要的。同时,算法设计也是最有挑战的,需要许多的实验并根据应用需要。

1.3.2          算法实现的优化

相对于算法设计的优化,算法实现的优化就简单一些了。基本上,算法实现的优化有两种思路。

第一,   避免计算。最好的优化就是“不计算”,仔细观察算法的实现,如果发现某些部分的计算结果在某些条件下是“还原”的,那就是说这个部分是做了“无用功“了。那么就可以尝试通过一些控制条件去避免计算。如Video decoerIDCT,统计一下各个分块的值分布,就可以改进算法实现,避免一些块的计算。提高效率。

第二,   重用计算。如果计算不可避免,就可以观察是否可以重用已有计算。这其实也是一种“避免计算”,只不过前提是调整算法实现,使得一些计算可以被重用。

 

2,代码优化

       如果说设计优化是全局性的,是“内行”做的事情,那么代码优化就是局部性的,是“外行“也可以做的事。如一个有代码优化经验的Audio Codec工程师虽然没有Video Codec的经验,但是同样可以对Video Codec的代码进行优化。因为代码优化依据的原理通常是可以适用于各个领域和平台的。如loop unroll通常是有效的。代码优化因为可以是“只见树木不见森林”,所以它的影响不是全局性的。套用一个代码优化专家的话说,代码优化通常可以使得一个慢的程序变的快一些。我的理解是,如果脱离了设计优化,慢的程序做再多的代码优化也不过是一个快了一些的“慢程序”。

       同理,好的代码优化能使好的设计如虎添翼。因为通常好的设计,或者说遵循局部性原理的设计更容易做代码优化,优化的效果也更好。

       代码优化大致可以分为以下两个部分:平台无关部分和平台相关部分

       平台无关部分是指一些普适的优化原则。如循环展开,减少分支,内联函数,指针运算,

地址对齐等等。

       平台相关部分就是通常所说的汇编代码优化。汇编代码可以对某个平台做最贴心的优化。首先各个平台都有不同的“高性能”指令,如C55的双MACARMV5Edsp指令,XSCALEWMMX等。其次,各个平台的流水线都不同,对指令排列有不同的要求,所以在汇编一级可以对指令做最好的调整。再次,只有在汇编一级,才可以抛开编译器,使程序思维最贴近CPU逻辑,并避免一些不必要的计算,带来最好性能。毕竟编译器的智商以及它对程序的了解通常比我们程序员要差一些。

 


  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值