C语言高效编程与代码优化语言高效编程与代码优化
简介
在最近的一个项目中,我们需要开发一个运行在移动设备上但不保证图像高质量的轻量级JPEG库。期间,我总结了一些让程
序运行更快的方法。在本篇文章中,我收集了一些经验和方法。应用这些经验和方法,可以帮助我们从执行速度和内存使用等
方面来优化C语言代码。
尽管在C代码优化方面有很多的指南,但是关于编译和你使用的编程机器方面的优化知识却很少。
通常,为了让你的程序运行的更快,程序的代码量可能需要增加。代码量的增加又可能会对程序的复杂度和可读性带来不利的
影响。这对于在手机、PDA等对于内存使用有很多限制的小型设备上编写程序时是不被允许的。因此,在代码优化时,我们
的座右铭应该是确保内存使用和执行速度两方面都得到优化。
声明
实际上,在我的项目中,我使用了很多优化ARM编程的方法(该项目是基于ARM平台的),也使用了很多互联网上面的方
法。但并不是所有文章提到的方法都能起到很好的作用。所以,我对有用的和高效的方法进行了总结收集。同时,我还修改了
其中的一些方法,使他们适用于所有的编程环境,而不是局限于ARM环境。
哪里需要使用这些方法?
没有这一点,所有的讨论都无从谈起。程序优化最重要的就是找出待优化的地方,也就是找出程序的哪些部分或者哪些模块运
行缓慢亦或消耗大量的内存。只有程序的各部分经过了优化,程序才能执行的更快。
程序中运行最多的部分,特别是那些被程序内部循环重复调用的方法最该被优化。
对于一个有经验的码农,发现程序中最需要被优化的部分往往很简单。此外,还有很多工具可以帮助我们找出需要优化的部
分。我使用过Visual C++内置的性能工具profiler来找出程序中消耗最多内存的地方。另一个我使用过的工具是英特尔的
Vtune,它也能很好的检测出程序中运行最慢的部分。根据我的经验,内部或嵌套循环,调用第三方库的方法通常是导致程序
运行缓慢的最主要的起因。
整形数
如果我们确定整数非负,就应该使用unsigned int而不是int。有些处理器处理无符号unsigned 整形数的效率远远高于有符号
signed整形数(这是一种很好的做法,也有利于代码具体类型的自解释)。
因此,在一个紧密循环中,声明一个int整形变量的最好方法是:
记住,整形in的运算速度高浮点型float,并且可以被处理器直接完成运算,而不需要借助于FPU(浮点运算单元)或者浮点型
运算库。尽管这不保证编译器一定会使用到寄存器存储变量,也不能保证处理器处理能更高效处理unsigned整型,但这对于
所有的编译器是通用的。
例如在一个计算包中,如果需要结果精确到小数点后两位,我们可以将其乘以100,然后尽可能晚的把它转换为浮点型数字。
除法和取余数
在标准处理器中,对于分子和分母,一个32位的除法需要使用20至140次循环操作。除法函数消耗的时间包括一个常量时间加
上每一位除法消耗的时间。
对于ARM处理器,这个版本需要20+4.3N次循环。这是一个消耗很大的操作,应该尽可能的避免执行。有时,可以通过乘法
表达式来替代除法。例如,假如我们知道b是正数并且b*c是个整数,那么(a/b)>c可以改写为a>(c*b)。如果确定操作数是无符
号unsigned的,使用无符号unsigned除法更好一些,因为它比有符号signed除法效率高。
合并除法和取余数
在一些场景中,同时需要除法(x/y)和取余数(x%y)操作。这种情况下,编译器可以通过调用一次除法操作返回除法的结
果和余数。如果既需要除法的结果又需要余数,我们可以将它们写在一起,如下所示:
通过2的幂次进行除法和取余数
如果除法中的除数是2的幂次,我们可以更好的优化除法。编译器使用移位操作来执行除法。因此,我们需要尽可能的设置除
数为2的幂次(例如64而不是66)。并且依然记住,无符号unsigned整数除法执行效率高于有符号signed整形出发。
上面两种除法都避免直接调用除法函数,并且无符号unsigned的除法使用更少的计算机指令。由于需要移位到0和负数,有符
号signed的除法需要更多的时间执行。
评论0
最新资源