Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2177623
  • 博文数量: 436
  • 博客积分: 9833
  • 博客等级: 中将
  • 技术积分: 5558
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-29 10:27
文章存档

2013年(47)

2012年(79)

2011年(192)

2010年(118)

分类: LINUX

2012-11-26 01:05:01

 编写高效程序需要的两类活动

  1 选择一组最好的算法和数据结构。

  2 编写出编译器能有效优化以转换成高效可执行代码的源代码。

 

  5-1  优化编译器相关

   编译器优化对用户不可见,其优化能力受限 如绝不改变程序正确行为,即使这个行为很繁琐,但是假如它是正确的,就不能更改;对程序行为及运行环境了解有限。

  我的理解:编译器能利用一些机会,主要通过对表达式的简化降低一些原操作的执行次序来进行,但是存在缺陷,制约优化的因素有:

 

 1存储器别名使用,我理解为在一个代码中,有可能两个不同名的指针可能指向同一个存储位置,因此编译器必须要假设不同的情况,像不同的指针指向存储器中同一位置,当然这么一来,会造成编译过程工作量更大,就造成了代码的效率无法进一步优化。

 

 2函数调用,大多数编译器不会判断一个函数是否无副作用,so任何函数都可能是优化候选者。因此即使代码中的函数有副作用,但是编译器肯定不会检测出来,因此极大制约对于代码的优化。

 

5-2 表示程序性能

   程序性能需要度量值,现在大多数程序用的度量标准为——每元素的周期数。

   按照书中的描述,我们能将一段代码中的一个操作过程所需时间可以抽象为一个一次函数t=a+bn其中n为被处理元素,而系数b被称为每元素的周期数CPE)。有这个函数我们知道,对于较大的n值,运行时间主要由线性因子来决定,因此用每元素周期数来作为度量程序性能的标准。

   一般程序员会用时钟周期来表示度量标准,这样的话,度量值不太依赖被评估的处理器的模型。(注:我的理解:如果要用纳秒来表示的话,则每个处理器都有根据其不同的特性,会有不同的数字,相对来说比较繁琐。而用时钟周期表示,一般是一个表达式,不是具体的某个数字)。

   新概念:最小二乘方拟合,循环展开技术。

 

优化代码性能的三种方式:(指不依赖目标机器性能的优化)

1:消除循环低效率

   代码移动——常见的优化实例,此类优化常用来对含有循环迭代的代码进行优化。

   此类优化能识别出代码中将执行多次但计算结果不改变的计算,此时此类代码在循环体内部,它不得不随着每一次的循环迭代过程一次次的进行计算,但是其结果根本不会改变,因此它没必要一次次的进行循环计算,此时我们就能将计算移动到代码前面的,不会被多次求值的部分。书中combine2函数通过把vec-length移出循环,大大缩减了代码的时钟周期。代码移动运用于包含迭代的的代码中,能有效消除循环的低效率。但是代码移动是不能由优化编译器来完成,而必须依靠程序员自己。

   编程中的警惕——渐进低效率问题

2:减少过程调用

   尽管过程调用能保证程序的模块性,但是在一些包含迭代的大型程序中,过程调用会带来相当大的开销,因此单单考虑提高程序性能,因尽量减少过程调用,如书中combine3函数,放弃了函数调用,而直接进行数据访问,无疑能大大提高程序性能。

3:消除不必要的存储器引用(这部分的机理还没完全理解清楚,需要继续理解

 5-7 现代处理器

  基本框架:ICU——指令控制单元,即控制器,负责从存储器中读指令并操作。

             EU——执行单元,即运算器,负责执行产生的基本操作。(功能单元包括:整数/分支、通用整数、浮点加法、浮点乘法/除法、[s1] 、存储)

 

   两个新概念:

1         指令退役的概念:一旦指令的操作完成了且所有导致这条指令的分支点都被确认为预测正确,则这条指令就可以退役了。任何对程序和状态的更新都只会在指令退役的时候发生。ICU内部的退役单元中有一些寄存器,其更新由退役单元来控制。

2         寄存器重命名的概念:最常见的控制操作数在执行单元间传送的机制

  

   总结:通过这周的学习,我对于不依赖于目标机器对代码性能进行优化的方式有了一个全面的认识,对于三种优化技术,前两种相对来说比较容易理解,对于第三种,消除不必要的存储器引用,希望能在讨论中加深理解。

  本周目标:在全面认识现代处理器的各个方面的基础上理解基于目标机器的特性对代码进行优化的方法。

  

 

 [s1]加载与存储有加法器来进行地址运算

阅读(704) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~