先从这一章开始,接下来就是存储、网络。先解决主要矛盾。仅记录部分。
- 【存储器别名使用】考虑传入参数为指针时,编译器不能直接优化。给的例子如下图所示。实际上写memcpy类似的函数,传入两个指针做数组复制时也需要确认dst指针指向的地址是否与src数组有重合。优化是编译器做的,代码是人写的,都需要细细考虑。
- 【代码移动】把重复计算提到循环外面。比如for (int i = 0; i < vec_int.size(); ++i)。当然我们不能确定,编译器是否会对此进行优化。
- 【分支预测&投机执行】
- ICU(Instruction Control Unit,指令控制单元)负责从指令告诉缓存中读指令序列,生成操作。退役单元(Retirement Unit)记录正在进行的处理,并确保它遵守机器级程序的顺序语义。
- EU(Execution Unit,执行单元):执行ICU生成的操作
- 【Pentium III算术操作的性能】整数除法(36)和浮点除法(38)的执行时间和发射时间感人。不同处理器的性能不一样,当时学的时候没注意到这点。
- 【循环展开】并行优化。如:奇数位相乘,偶数位相乘。但并行度受到寄存器个数限制。
- 【优化程序性能基本策略】
- 高级设计:选择适当的算法和数据结构。
- 基本编码原则:
- 消除连续的函数调用。在可能时,将计算移到循环外。
- 消除不必要的存储器引用。引入临时变量来保存中间结果。计算完最后的值,再把结果存放到数组或全局变量中。
- 低级优化
- 尝试各种与数组代码相对的指针形式。
- 循环展开
- 迭代分割
- 最后,正确才是最重要的!
- 【程序剖析(profiling)】Unix系统提供了一个剖析程序GPROF。
- 计时不是很准确。基于一个简单的间隔技术。
- 调用信息相当可靠。
- 默认不显示对库函数的调用。