今天在看《深入理解计算机系统》时看到了性能优化,认识到了之前从未考虑过的问题。
妨碍优化的因素:
1.计算依赖的指针p和q 是否指向存储器中同一个位置
2.函数调用
举例说明:
1)
void twiddle1(int *xp,int *yp){
*xp+=*yp;
*xp+=*yp;
}
void twiddle2(int *xp,int *yp){
*xp+= 2 * *yp;
}
乍一看,这两个过程似乎有相同的行为,他们都是将存储在由指针yp 指示的位置处的两次加到指针xp指示的位置处的值。另一方面,函数twiddle2函数效率更高一些。它只要求3次存储器引用(读*xp,读*yp,写*xp)而twiddle1需要6次(2次读*xp,2次读*yp,2次写*xp)。因此,如果要编译器编译过程twiddle1,我们会认为基于twiddle2执行的计算能产生更有效的代码。
不过,考虑xp等于yp的情况,此时,函数twiddle1会执行下面的计算:
*xp += *xp;
*xp += *xp;
结果是xp的值会增加4倍。另一方面,函数twiddle2会执行下面的计算:
*xp += 2 * *xp;
结果是xp的值会增加3倍。编译器不知道twiddle1会如何被调用,因此它必须假设参数xp 和yp可能会相等。因此,它不能产生twiddle2风格的代码作为twiddle1的优化版本。
2)
int f();
int func1(){
return f()+f()+f()+f();
}
int func2(){
return 4*f();
}
最初看上去两个过程计算的都是相同的结果,但是func2只调用了f 1次,而func1调用了4次。以func1作为源时,会很想产生func2风格的代码,不过,考虑下面f的代码;
int counter=0;
int f(){
return conter++;
}
这个函数有个副作用,它修改了全局程序状态的一部分。改变了调用它的次数会改变程序的行为。特别的,假设开始时全局变量counter 都设置为0,对 func1的调用会返回 0+1+2+3=6 ,而func2的调用会返回4*0=0.