深入理解计算机系统9个重点笔记

引言

深入理解计算机系统,对我来说是部大块头。说实话,我没有从头到尾完完整整的全部看完,而是选择性的看了一些我自认为重要的或感兴趣的章节,也从中获益良多,看清楚了计算机系统的一些本质东西或原理性的内容,这对每个想要深入学习编程的程序员来说都是至关重要的。只有很好的理解了系统到底是如何运行我们代码的,我们才能针对系统的特点写出高质量、高效率的代码来。这本书我以后还需要多研究几遍,今天就先总结下书中我已学到的几点知识。

深入理解计算机系统(原书第2版) PDF清晰中文版  下载见 

 

重点笔记

编写高效的程序需要下面几类活动:

选择一组合适的算法和数据结构。这是很重要的,好的数据结构有时能帮助更快的实现某些算法,这也要求编程人员能够熟知各种常用的数据结构和算法。

编写出使编译器能够有效优化以转换成高效可执行的源代码。因此,理解编译器优化的能力和局限性是很重要的。编写程序方式中看上去只是一点小小的变动,都会引起编译器优化方式很大的变化。有些编程语言比其他语言容易优化得多。C语言的某些特性,例如执行指针运算和强制类型转换的能力,使得编译器很难对其进行优化。

并行技术,针对处理运算量特别大的计算,将一个任务分成多个部分,这些部分可以在多核和多处理器的某种组合上并行地计算。

让编译器展开循环
说到程序优化,很多人都会提到循环展开技术。现在编译器可以很容易地执行循环展开,只要优化级别设置的足够高,许多编译器都能例行公事的做到这一点。用命令行选项“-funroll-loops”调用gcc,会执行循环展开。

性能提高技术:

高级设计,为手边的问题选择适当的算法和数据结构,要特别警觉,避免使用会渐进地产生糟糕性能的算法或编码技术。

基本编码原则。避免限制优化的因素,这样编译器就能产生高效代码。

消除连续的函数调用。在可能时将计算移到循环外,考虑有选择的妥协程序的模块性以获得更大效率。

消除不必要的存储器引用。引入临时变量来保存中间结果,只有在最后的值计算出来时,才能将结果放到数组或全局变量中。

低级优化。

尝试各种与数组代码相对的指针形式。

通过开展通过展开循环降低循环开销。

通过诸如迭代分割之类的技术,找到使用流水线化的功能单元的方法。

说到性能提高,可能有人会有一些说法:

(1)不要过早优化,优化是万恶之源;
(2)花费很多时间所作的优化可能效果不明显,不值得;
(3)现在内存、CPU价格都这么低了,性能的优化已经不是那么重要了。
 ……

其实我的看法是:我们也许不必特地把以前写过的程序拿出来优化下,花费N多时间只为提升那么几秒或几分钟的时间。但是,我们在重构别人的代码或自己最初开始构思代码时,就需要知道这些性能提高技术,一开始就遵守这些基本原则来写代码,写出的代码也就不需要让别人来重构以提高性能了。另外,有的很简单的技术,比如说将与循环无关的复杂计算或大内存操作的代码放到循环外,对于整个性能的提高真的是较明显的。

如何使用代码剖析程序(code profiler,即性能分析工具)来调优代码?
程序剖析(profiling)其实就是在运行程序的一个版本中插入了工具代码,以确定程序的各个部分需要多少时间。
Unix系统提供了一个profiling叫GPROF,这个程序产生两类信息:

首先,它确定程序中每个函数花费了多少CPU时间。
其次,它计算每个函数被调用的次数,以执行调用的函数来分类。还有每个函数被哪些函数调用,自身又调用了哪些函数。

使用GPROF进行剖析需要3个步骤,比如源程序为prog.c。
1)编译: gcc -O1 -pg prog.c -o prog(只要加上-pg参数即可)
2)运行:./prog
 会生成一个gmon.out文件供 gprof分析程序时候使用(运行比平时慢些)。
3)剖析:gprof prog
 分析gmon.out中的数据,并显示出来。

剖析报告的第一部分列出了执行各个函数花费的时间,按照降序排列。
剖析报告的第二部分是函数的调用历史。
具体例子可参考网上资料。

GPROF有些属性值得注意:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/16647.html