CSAPP:优化程序性能

优化程序性能这章作为CSAPP中最闪光的一章,其重要程度不言而喻。此实验分为了两个部分:第一部分是对一个多项式计算的优化;第二部分是对矩阵代码的优化。


首先,我们必须了解一些优化程序的常识。
编写高效的程序需要两个方面下足马力:第一,我们必须选择一组最好的的算法和数据结构;第二,我们必须编写出编译器能够有效优化以转换成高效可执行代码的源代码。那么此时,我们就需要理解优化编译器的能力和局限性。它的局限性表现在两个方面:

第一,存储器别名;
 

提示:考虑*xp == *yp的情况。

第二,函数调用。

提示:考虑fun(x)里面是一个全局变量或静态变量,并且递增。
接下来将逐个介绍优化程序的方法。
第一个方法,代码移动。什么是代码移动呢?它就是把在循环中执行多次但结果却固定不变的代码移动到循环之外,这是最简单的优化。
第二个方法,减少过程调用。为什么要减少函数调用呢?因为每次调用一个函数,这个函数都可能会执行冗余的操作,比如数组边界检查,类型检查等。举例来说,如果我们需要调用一个函数来获得数组中的一个元素,我们可以首先获得数组首地址,然后通过索引访问每个元素,而非调用一个函数,然后检查数组是否越界,然后才返回元素值。
第三种方法,消除不必要的存储器引用。也就是说,在循环体中不使用指针来存放结果,而使用临时变量。为什么呢?目的就是减少读、写内存地址的时间。


随着对优化的深入,研究汇编代码以及理解现代处理器是如何执行计算则变得很重要。下面继续了解几种优化技术。
第四种方法,循环展开 。什么是循环展开?其思想是在一次迭代中对多个数组元素进行访问和合并操作。那这样做有什么原因或者说带来了什么好处呢?受限于资源约束,每个周期内只有两个功能单元可以执行数据相关的操作,然而一个周期内可能有涉及到数据的多个操作。那么,这些操作就不能在同一周期内完成,必须暂停等待,降低性能。通过循环展开可以在每次迭代中执行更多的数据操作,避免一个周期内产生多于两个操作,从而降低循环开销。

理想情况下的整数加法调度

实际资源受限的情况下,整数加法的调度

优化后,三次循环展开的整数加法的调度

 

第五种方法,迭代分割 。什么是迭代分割呢?我们知道处理器的几个功能单元是流水线化的,这说明它们在一个操作完成之前可以开始另一个新的操作。但是,我们的代码没有这种能力。当执行当前操作时,处理器会处理其它事务(一般不会暂停),直到本操作完成,才开始下一个操作。这严重影响了程序的性能。而通过迭代分割,则可以很好地缓解此问题,以提高性能。迭代分割其实就是把一个操作分割成两个或更多的部分,并在最后合并结果以提高性能。产生二路并行或n路并行,提高了程序的并行性。

 

理想情况下的整数乘法调度

实际资源受限的情况下,整数乘法的调度

优化后,二次展开、二次并行的整数乘法操作调度

比较直观的例子

运用上面的方法来优化第一部分多项式代码,思考!

对于第二部分的矩阵优化,我们用到的核心思想就是利用局部性原理,包括时间局部性和空间局部性,避免大幅度地跨越内存块。具体的示例在第三章“程序的机器级表示”的嵌套数组以及第六章“存储器层次结构”的局部性原理中讲述。

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值