优化编译器的能力和局限性
- 以选项-Og调用gcc让gcc使用一组基本的优化,选项-O1或更高会让它使用更大量的优化
- 局限性:1.内存别名使用,两个指针指向同一个内存位置 2.函数调用,改变调用次数会改变程序的行为
表示程序性能
- 使用每元素的周期数(CPE)来表示程序性能,优化程序的目标是减小CPE
消除循环的低效率
- 代码移动:识别执行多次但是计算结果不会改变的计算
- 频繁读取内存导致执行时间变长
减少过程调用
理解现代处理器
- 处理器的整体设计主要分为两部分:指令控制单元(ICU):负责从内存中读出指令序列,执行单元(EU)负责执行这些操作
- 投机执行:处理器会开始取出位于它预测的分支会跳转到的地方的指令
- 延迟:表示完成运算所需要的总时间
- 发射时间:表示两个连续的同类型的运算之间需要的最小时钟周期数
- 容量:表示能够执行该运算的功能单元的数量
- 延迟界限:一系列操作必须按照严格顺序执行
- 吞吐量界限:根据功能单元产生结果的最大速率给出的CPE最小界限
- 对于形成循环的代码片段,寄存器分为四类:
- 只读:在循环中不被修改
- 只写:作为数据传送操作
- 局部:在循环内部被修改,迭代与迭代之间不相关
- 循环:一次接待中产生的值会在另一次迭代中用到
循环展开
- 循环展开是一种程序变换,通过增加每次迭代计算的元素的数量,减少循环的迭代次数
提高并行性
- 2*2循环展开,使用两次循环展开,使每次迭代合并更多的元素,关键路径为两条
- 2*1a循环展开,称为重新结合变换,每次迭代内的第一个乘法不需要等待前一次的累积值就可以执行
一些限制因素
- 寄存器溢出:并行度超过了可用的寄存器数量
- 分支预测和预测错误处罚
理解内存性能
- 加载的性能
- 储存的性能,写/读相关
性能提高
- 高级设计:第一是针对具体的问题选择适当的算法和数据结构
- 基本编码原则:第二是遵循一些基本的编码规则
- 低级优化:第三是根据硬件的设计,利用循环展开等技术来提高指令集并行