1.编写高效程序
需要注意以下几点,
第一,必须选择一组适当的算法和数据结构;
第二,必须编写出编译器能够有效优化以转换成高效可执行代码的源代码;因此,理解优化编译器的能力和局限性是很重要的,编写程序方式中看上去只是一点小小的变动,都会引起编译器优化方式很大的变化;
第三,针对处理运算量特别大的计算,将一个任务分成多个部分,这些部分可以在多核和多处理器的某种组合上并行地计算。
大多数编译器,包括GCC,一直都在更新和改进,特别是在优化能力方面。
2.表示程序性能
引入度量标准---每元素的周期数(cycles per element,CPE),作为一种表示程序性能并指导我们改进代码的方法。CPE这种度量标准帮助我们在更细节的级别上理解迭代程序的循环性能。这样的度量标准对执行重复计算的程序来说是很适当的。例如,处理图像中的像素,或是计算矩阵乘积中的元素。
处理器活动的顺序是由时钟控制的,时钟提供了某个频率的规律信号,通常用千兆赫兹(GHz),即十亿周期每秒来表示。从程序员的角度来看,用时钟周期来表示度量标准要比纳秒或皮秒来表示有帮助的多。用时钟周期来表示,度量值表示的是执行了多少条指令,而不是时钟运行的有多快。
3.减少过程调用
过程调用会带来开销,而且妨碍大多数形式的程序优化。
4.消除不必要的内存引用
5.功能单元的性能
从上图可以看到,从整数运算到浮点运算,延迟是增加的。还可以看到加法和乘法的发射时间都为1,意思是说在每个时钟周期,处理器都可以开始一条新的这样的运算。这种很短的发射时间是通过使用流水线实现的。流水线化的功能单元实现为一系列的阶段(stage),每个阶段完成一部分的运算。发射时间为1的功能单元被称为完全流水线化的:每个时钟周期可以开始一个新的运算。出现容量大于1的运算是由于有多个功能单元,就如参考机一样。
同时,除法器(用于整数和浮点除法,还用来计算浮点平方根)不是完全流水线化的——它的发射时间等于它的延迟,这就意味着在开始一条新运算之前,除法器必须完成整个除法。还可以看到,对于除法的延迟和发射时间是以范围的形式给出的,因为某些被除数和除数的组合比其他的组合需要更多的步骤。除法的长延迟和长发射时间使之成为了一个相对开销很大的运算。
表达发射时间的一种更常见的方法是指明这个功能单元的最大吞吐量,定义为发射时间的倒数。
第五章小结