深入理解计算机系统笔记一

   我看的是《深入理解计算机系统》原书第三版,这真的是一本相见恨晚的好书。看了几天,有些内容已经在实际编程中获益了。我重点关注的是优化程序性能。作为程序员,我们无须为了写出高效代码而去了解一些编译器的内部工作。但是,为了在C程序中作出好的编码选择,我们确实需要了解一些机器代码以及编译器将不同的C语句转化为机器代码的方式。比如一个switch语句是否总是比一系列的if-else语句高效得多while循环比for循环更有效吗指针引用比数组索引更有效吗?(从目前我个人的经验来看,确实要更有效,周六刚测试的代码,比较简单的代码,大概快了10ms,目前我心中对这个原因还是有一定的想法,但还不确定,至少指针的++的操作要比通过索引寻址的方式直觉上看来要简单,近水楼台先得月)。为什么将循环求和的结果放到一个本地变量中,会比将其放到一个通过引用传递过来的参数中,运行起来快很多呢?(因为减少了对存储器的访问?)为什么我们只是简单地重新排列一下算术表达式中的括号就能让函数运行的更快?(在书中称为重新结合变换,因为括号改变了向量元素之间的合并顺序,比如 acc = (acc op data[i]) op data[i+1]; 重新排列后, acc = acc op (data[i] op data[i+1]);后面的这种方式增加了可以并行执行的操作数量。

   最让我印象深刻的是关于编译器对程序的安全优化,也就是说对于程序可能遇到的所有可能的情况,在C语音标准提供的保证之下,优化后得到的程序和未优化后的版本有一样的行为,限制编译器只进行安全的优化。为了理解决定一种程序转换是否安全的难度,让我们来看看下面的这两个过程

void twiddle1(long *xp, long *yp)
{
    *xp += *yp;
    *xp += *yp;
}

void twiddle2(long *xp, long *yp)
{
    *xp += 2* *yp;
}

   乍一看,这两个过程似乎有相同的行为。他们都是讲存储在指针yp指示的位置处的值两次加到指针xp指示的位置处的值。另一方面,函数twiddle2效率更高一些。它只要求3次内存引用(读*xp,读*yp,写*xp),而前者需要6次。因此,如果要编译器编译过程twiddle1,我们会认为twiddle2执行的计算能产生更有效的代码。

    不过,考虑xp指针等于yp的情况。此时函数twiddle1会执行,下面的代码段,结果xp的值为原来的4倍。

*xp += *xp;
*xp += *xp;

   而函数twiddle会执行下面的计算

*xp += 2* *xp;

结果是xp的值等于原来的3倍。通过这一个例子,我是跪服了搞编译器优化的大神。

猜你喜欢

转载自blog.csdn.net/lucky_greenegg/article/details/81293226