视频地址:
http://player.bilibili.com/player.html?aid=31289365&bvid=BV1iW411d7hd&cid=89610450&page=10
课件地址:
对应书中的第五章。
如有错误请指出,谢谢。
- 使用内联方式来优化函数调用问题
- 优化方法:
- 基本编码原则:
- 消除连续的函数引用:识别要执行多次(比如在循环内)但是计算结果不会改变的计算,将该计算移到前面。同时也考虑减少循环中函数的调用。
- **消除不必要的内存引用:**当在循环中使用指针时,会反复对内存进行读写,我们可以引入一个临时变量来保存中间结果,使其保存在寄存器中,就无需涉及内存引用了,最终再将寄存器中的值保存到指针中。
- 低级优化:
- **kx1循环展开:**一个循环中计算多个操作,减少需要的循环次数,能减少不必要的操作,但是没有消除数据相关,无法突破延迟界限。
- **kxk循环展开:**声明多个独立变量,在循环中独立计算,能减少循环次数,并使用多个功能单元及其流水线,能消除数据相关突破延迟界限。当 $k \geq C \times L$ 时接近吞吐量界限,其中C为操作容量、L为操作延迟。
- **重新结合:**通过修改结合方法,来减少目标寄存器上的操作,由此减少关键路径上的操作数。
- 反复测试代码,使得汇编代码产生条件传送。
- 上下相同寄存器才会构成一段数据相关链
- **注意:**延迟是指执行一个操作所需的时钟周期,但是由于功能单元存在流水线,所以可以每个时钟周期都开始一个操作。只有当两个操作之间存在数据相关时,无法使用流水线了,才考虑操作的延迟。
- 数据相关是针对寄存器而言的
- 要在更大范围观察写/读相关,不一定存在一个迭代中,可能在相邻迭代中,只要发现有存储操作,而后执行相同地址的加载操作,就会有写/读相关。
编写高效程序要做到:
- 选择合适的算法和数据结构
- 编写出编译器能够有效优化以转化成高效可执行代码的源文件**(重要)**
- 针对处理运算量较大的计算,可以将一个任务分成多个部分,然后在多核和多处理器的某些组合上并行计算。(第12章再介绍)