关于程序运行效率的一点见解

Posted on

最近在看计算机组成原理等4本考研书籍...发现其实回过头来看这些当年没认真学的书的话还是有不少收获的. 当年小白的我只知道编程看语言类的书籍,无法理解数据结构,计算机组成原理一类书对编程的影响. 刚开始学这本书的时候就感觉我一个搞软件编程的看硬件干嘛.又是指令又是寄存器啥的,还有那可怕的电路图... 看的真头大啊,不过其实想想,这门课要是真没用学校也不会开考研也不会考啊!当年真是图样图森破啊...

大一的时候一直以为搞软件的就要多学点编程语言...我现在倒是学了不少.到头来没一个拿的出手的,还真是可悲 广度是有了但是没深度,同样的语言人家编程风格和效率就是比你高.这个是在什么C#本质论 C++ primer里面学不到的 东西,说深了就是加编程素养.是不断积累的,不是看一本书就能迅速提升的东西.只上过培训班的程序员永远也不可能明白 学习计算机组成原理会对编程有更深入的了解.最终写的代码也只是知其然而不知其所以然.

编程素养是通过各方面计算机知识的综合培养才能得到提高的.接下来我就举个例子来谈谈学过组成原理对编程的理解和 提高.例子很简单,就是关于数组的遍历.一个二维数组,假定是10*10的吧.那么遍历输出的话,大家肯定都会的,很简单.

for(i=0;i<10;i++)
    for(j=0;j<10;j++)
       printf(a[i][j]);

这个是很简单的两层for循环,我写的是伪代码,变量定义输出什么的就不要吐槽了.学过数据结构的同学应该都明白虽然二维 数组都用矩阵来表示,但是实际储存的时候一般都是按照行优先的方式储存的.我的这个版本是先行遍历再列遍历的.

    for(j=0;j<10;j++)
            for(i=0;i<10;i++)
               printf(a[i][j]);

那么先列遍历再行遍历呢?大家一般都会觉得这个其实没什么差别吧.用数据结构的思想来说,空间复杂度和时间复 杂度都是一样的,运行起来没啥区别的.当然对于现在的高速CPU和这个元素比较少的数组来说其实也没多大差别,但是不能 因为这个就去忽略程序的效率问题.

为了讲述这个问题,首先的了解计算机的基本运行原理.首先程序是放在内存中的,但是执行程序需要用CPU来计算.因为CPU运行 速度极快,但是内存速度却没有显著的提高.所以引入了高速缓存也就是Cache,首先把内存中的程序调入高速缓存中.然后CPU再从 Cache中取出数据进行运算.但是因为Cache的容量极小,但是内存很大,根据程序访问的局部性原理.指令通常是顺序存放, 顺序执行的,数据一般也是聚集的存储在一起的.所以调入Cache中的数据基本上会是一段时间内CPU欲调用的数据.

当CPU发出度数据的请求时,如果访问的地址在Cache中即命中,那么直接从Cache中读取数据,和主存无关;如果Cache不命中, 则仍需访问主存,并把此地址所在的块一次性都调入Cache内.

显然,如果命中率高的话,那么程序直接的速度就更快.对比行遍历和列遍历.发现行遍历每次都是按顺序取数据的,因为是按照行优先方式 进行存储的嘛,所以命中率必然高.而列遍历的话每次取的都不是相邻的数据,会导致命中率大大降低,运行效率低.所以一会写程序的话 遇到数组遍历的话肯定要使用行遍历更好.

类似的问题还有GOTO语句,大一的时候老师明令禁止不准在程序中使用GOTO语句,但是就是不说为什么...学过计算机组成原理也就 明白了,因为GOTO语句违反了程序顺序执行的原则,使程序运行效率不高,而且程序读起来也很麻烦.

到此,对编程效率的见解就结束了,如果有什么纰漏的地方,还请大家指正,感谢您能读到最后~

comments powered by Disqus