优化程序性能
程序的目标:
- 清晰简洁
- 高性能
高性能的手段:
- 适当的算法和数据结构
- 编写易让编译器优化的代码
- 多线程
本章的核心是:
- 编写易让编译器优化的代码
- 结合处理器来优化代码的执行
优化编译器的能力和局限性
哪些编码方式是编译器不好优化的?
内存别名使用
:编译器无法判断不同的指针是否会指向内存的同一个位置
代码案例:1
2
3
4
5
6
7void twiddle1(long *xp, long *yp){
*xp += *yp;
*xp += *yp;
}
void twiddle2(long *xp, long *yp){
*xp += 2 * *yp;
}
函数调用
:编译器无法判断函数是否存在副作用,如修改了全局变量
代码案例:1
2
3
4
5
6
7long func();
long func1(){
return f() + f() + f() + f();
}
long func2(){
return 4*f();
}
表示程序性能
如何衡量程序的性能?什么是每元素的周期数(CPE)
?
使用每元素的周期数(CPE)
衡量,“元素”理解为需要被处理的数据量。每元素的周期数(CPE)
理解为处理元素所需的时钟周期
上图中的斜率就是每元素的周期数(CPE)
什么是最小二乘拟合
,有什么用?
程序示例
示例代码:合并运算
优化级别对性能的影响
消除循环的低效率
循环中的低效代码?如何优化?
对上述的示例代码
循环中反复调用了一个结果不变得函数
改进:
编译器为何不自动优化?
受函数调用的副作用
影响
消除不必要的寄存器消耗
哪些代码会造成不必要的寄存器消耗?如何优化?
上述案例代码中
1 | *dest = *dest OP val |
*dest的结果没有任何作用
但是却造成了寄存器的额外消耗
改进:
编译器为何不自动优化?
受内存别名使用
的影响
理解现代处理器
剩下的章节内容:
- 了解现代处理器的乱序执行
- 利用乱序、并行提高程序性能