除了多线程切换,避免CPU闲置浪费,还有一点 。
我先问一个问题 。
//@author :www.yaoxiaowen.comint main(){ //我们执行任务的代码 return 0;}对于一个应用/进程而言,它都应该有一个入口 。(虽然不一定需要我们直接写main函数) 。入口函数内部就是我们的任务代码,任务代码执行完了这个应用/进程也就结束了 。这个很好理解,比如测试工程师写的一个测试case 。跑完了这个任务就结束了 。
但是 有些程序,比如一个 app,你打开了这个app 。不做任何操作 。这个界面会一直存在,也不会消失 。思考一下这是为什么 。因为这个app进程肯定也要有一个main入口 。main里面的任务代码执行完了,就应该结束了 。而一个程序的代码/指令数目肯定是有限的 。但该app在我们不主动退出情况下,却不会主动结束 。
所以这个app进程的入口main来讲,其实是这样的 。
//@author :www.yaoxiaowen.comint main(){ boolean flag = true; while (flag){ //我们执行任务的代码 } return 0;}并且不仅如此,在一个程序内部,也有大量的for,while等循环语句 。
那么当我们把这些相关的代码指令送到了主存,或者更高一级的缓存时,那么CPU在执行这些指令时,存取速度自然快了很多 。
在执行一个程序时,启动阶段比较慢,因为需要从磁盘读取数据 。(而CPU在这个阶段也没闲置浪费,它会进行线程切换执行其他任务) 。但是数据被送往内存之后,它执行起来就会快多了,并且伴随着执行过程,还可能越来越快,因为这些数据,有可能被一级一级的向上送,从L4,送到L3,再送到L2,L1
so,上述那个问题的答案,已经解释的比较清楚了吧 。
局部性原理(Principle of locality)locality对于硬件和软件系统的设计和性能都有着重要的影响 。对于我们理解存储器的层次结构也必不可缺 。
程序倾向于引用临近于与其他最近引用过的数据项的数据项 。或者最近引用过的数据项本身 。这种倾向性,我们称之为局部性原理 。它通常有以下两种形式:
时间局部性(temporal locality):被引用过一次的存储器位置的内容在未来会被多次引用 。空间局部性(spatial locality):如果一个存储器位置的内容被引用,那么它附近的位置也很大概率会被引用 。一般而言,有良好局部性的程序比局部性差的程序运行的更快 。现代计算机系统的各个层次,从硬件到操作系统、再到应用程序,它们的设计都利用了局部性 。
当然,光说理论的东西比较玄乎 。我们来看实际的例子 。
//@author www.yaoxiaowen.comint sum1(int array[N]){ int i, sum = 0; for(i = 0; i < N; i++) sum += array[i]; return sum;}在这个程序中,变量sum,i在每次循环迭代时被引用一次,因此对sum和i来说,有较好的时间局部性 。
对变量array来说,它是一个int类型数组,循环时按顺序访问array,因为一个C数组在内存中是占用连续的内存空间 。因而的较好的空间局部性,
再来看一个例子:
//@author www.yaoxiaowen.comint sum2(int array[M][N]){ int i, j, sum = 0; for(i = 0; i < M; i++){ for(j = 0; j < N; j++) sum += array[j][i]; }return sum;}这是一个空间局部性很差的程序 。
假设这个数组是array[3][4],因为C数组在内存中是按行顺序来存放的 。所以sum2对每个数组元素的访问顺序成了这样:0,4,8,1,5,9…… 7,11 。所以它的空间局部性很差 。
但是幸运的是,一般情况下软件编程天然就是符合局部性原理的 。比如程序的循环结构 。
假设CPU需要读取一个值,int var,而var在L4主存上,那么该值会被依次向上送,L4->L3->L2,但是这个传递的过程并不是单纯的只传递var四个字节的内容,而是把var所在的内存块(block),依次向上传递,为什么要传递block?因为根据局部性原理,我们认为,与var值相邻的值,未来也会被引用 。
存储器的层次结构,数据进行传送时,是以block(块)为单位传送的 。在整个层次结构上,越往上,block越小而已 。
存储器层次结构中的缓存
洋洋洒洒的扯了那么多,我相对于所谓的 存储器层次结构读者应该有一个基本的认识,有些地方介绍的 不够严谨,但是本文的目的也就是让大家理解基本思想 。
归根到底,它就是一个缓存(caching)的思想,并且其实不复杂,
我们做app开发时,对于app中活动页面等,都是后台发给我们图片url,我们下载后才显示在app上,这时我们总要使用 Glide,Picasso 等图片缓存框架来把下载好的图片缓存在手机本地存储上 。这样下次打开app时,如果这个图片链接没有改变,我们就直接拿手机本地缓存的图片来进行显示,而不用再从服务器上下载了 。如果图片链接改变了,则重新下载 。为什么要这么做?因为从服务器上下载比较慢,而手机本地存储(ROM)中读取就会快很多 。
推荐阅读
- 华为手机应用怎么移到sd卡 华为手机应用移到sd卡的方法是什么
- 9月3日是什么日子 9月3日是哪个节日
- 荣耀9x是什么屏幕荣耀9x什么屏幕
- 三红蜜柚是哪里产的 三红蜜柚是什么地方的
- 12星座女和渣男谈恋爱是什么体验?
- 最大数字是什么单位 数字办公室是什么单位
- 桂林山水甲天下的下一句是什么谚语 桂林山水甲天下的下一句是什么?
- 福特是什么旗下的
- 怎样清洗泡菜坛子 清洗坛子的步骤是什么
- 奔驰abs和防滑灯亮是什么原因?