现代计算机系统现代计算机系统与冯·诺依曼计算机几乎没有什么区别。最大的区别在于冯诺依曼计算机是以运算单元为中心,而现代计算机是以内存为中心的:我们主要看一下与存储相关的部件:内存内存用于存储数据和程序。内存包括主内存和辅助内存主内存:直接与CPU交换信息,也就是我们熟悉的内存。掉电后存储器中的数据会丢失:辅助存储器可以作为主存储器的备份存储器,不直接与CPU交换信息。它的容量比主存大,但速度比主存慢。如机械硬盘、固态硬盘等。硬盘上的数据断电后不会丢失,硬盘是永久性存储设备。辅助存储、输入设备、输出设备统称为IO设备;主机一般包括:CPU、主存。我们先来看看内存的层级结构,初步了解内存的各个组成部分。我们可以发现内存越快,内存越快,相应的价格会变贵!寄存器CPU中还有一个常用的部件:寄存器,是CPU内部用来存放数据的一些小的存储区,用来暂存运算中涉及的数据和运算结果。寄存器由电子电路组成,存取速度非常快。寄存器的成本相对较高,所以数量较少。CPU时钟周期CPU时钟周期:通常为节拍脉冲或T周期,是主频的倒数,是CPU中的基本时间单位。通常我们玩游戏时常说超频,超频就是CPU的主频。例如主频3.0GHZ的CPU,一个时钟周期约0.3纳秒,访问内存约120纳秒,访问固态硬盘约50-150微秒,访问机械硬盘约1-10毫秒,最后是网络访问是最慢的,大约几十毫秒。大家可能对时间不是很敏感,所以如果我们把一个时钟周期算作1秒,内存访问大概6分钟,固态硬盘大概2-6天,传统硬盘大概1-12个月,入网时间约为1-12个月。访问将需要数年时间!我们可以发现CPU的速度和内存等存储的速度根本不在一个数量级上。缓存为了弥补CPU和内存的性能差异,在CPU内部引入了CPUCache,也就是缓存。CPUCache采用SRAM(StaticRandom-AccessMemory)芯片,也叫静态随机存取存储器。只要有电,数据就可以存在,但一旦断电,数据就会丢失。CPUCache通常分为大小不同的三级缓存,分别是L1Cache、L2Cache和L3Cache。备注CPU访问一级缓存所需的时间为2到4个时钟周期。每个CPU核心都有自己的L1Cache,L1缓存通常分为指令缓存和数据缓存。L2cache10~20clockcyclesL2cache也是每个CPUcore的L3cache20~60clockcyclesL3cache被多个CPUcores共享我们可以发现CPUcore离cache越近访问速度越快。程序执行时,内存中的数据会先被加载到共享的L3Cache中,然后加载到每个核心独有的L2Cache中,最后进入最快的L1Cache中才被CPU读取。层次关系如下图所示:主存主存,直接与CPU交换信息,就是我们熟悉的内存。它使用一种叫做DRAM(DynamicRandomAccessMemory)的芯片,也叫动态随机存取存储器。断电后内存中的数据将丢失。DRAM芯片具有更高的密度、更低的功耗和更大的容量。成本比SRAM芯片便宜很多,但速度比SRAM芯片慢很多。存储器的速度在200到300个时钟周期之间。固态硬盘(SSD),数据直接存储在闪存颗粒中,主控单元记录数据存储位置和数据操作。每个闪存颗粒的存储容量是有限的;但它相对于内存的优势在于断电后数据仍然存在。SSD固态硬盘的读写速度虽然比内存慢10~1000倍左右,但比机械硬盘快很多。当然,价格也要贵很多。不过随着时代的发展,固态硬盘的价格也在逐渐接近机械硬盘。机械硬盘机械硬盘(_HardDiskDrive,HDD_),它通过物理读写来访问数据。机械硬盘向磁盘写入数据,磁盘转动,机械臂移动。与原来的数据读写方式相比,就像现代留声机的工作原理一样。由于转盘速度和指针寻址时间的限制,其存取速度很慢,比内存慢10W左右。当然,机械硬盘也有其优点:容量大、价格便宜、数据恢复难度低,所以将数据存储在机械硬盘中更加安全。压榨CPU性能带来的问题由于CPU的速度非常快,而且非常昂贵,所以我们必须像剧组的驴子一样,充分压榨CPU,让它不停地工作。为了节省成本,现代计算机将这些内存充分组合在一起。由于这些硬件的数据访问速度的差异,计算机系统编程中会出现各种问题:顺序问题为了充分压榨CPU的性能,CPU会乱序执行或者语言的编译器会重新排列指令让CPU不停的工作,但同时也会造成顺序问题。为了让指令的执行尽可能在CPU中同时运行,采用了指令流水线。一条CPU指令的执行过程可以分为4个阶段:取指、译码、执行和回写。这4个阶段分别由4个独立的物理执行单元完成。理想的情况是:指令之间没有依赖关系,流水线的并行度可以最大化。但是,如果两条指令之间存在依赖关系,如数据依赖、控制依赖等,则后一条语句必须等到前一条指令完成后才能开始。因此,为了提高流水线的运行效率,CPU会对独立的前导指令进行适当的乱序和调度。还有一种情况,编译器会重新排列指令,比如java语言,JVM编译器会优化其指令的重新排序(instructionrearrangement)。所谓指令重排,是指在不改变原有语义的情况下,通过调整指令的执行顺序,使程序运行得更快。JVM并没有规定编译器优化相关的内容,也就是说JVM可以随意优化指令重排序。无论是编译时的指令重排,还是CPU的乱序执行,其主要目的都是为了“填满”CPU内部的指令流水线,提高指令执行的并行性,充分利用CPU的高性能。中央处理器。可见性问题计算机的CPU为了平衡CPU寄存器和内存的速度差异,增加了缓存,但同时也导致了可见性问题。我们知道,当程序执行时,一般的CPU都会从内存中读取数据进行计算。CPU完成计算后,需要将数据放回内存中。CPU的多个核心参与程序运行时,从内存中读取一个共享变量的数据,不同核心进行各自计算时,将计算出的值放入各自的缓存中,而不是选择立即写入内存(CPU写入内存的时机不确定)。那么在CPU的缓存中,这个共享变量可能存储了不同的数据,从而导致了缓存的可见性问题。即一个线程对数据的修改,其他线程是看不到的。原子性问题操作系统为了平衡CPU和I/O设备的速度差异,在时分多路复用CPU中加入了进程和线程的概念,但同时也导致了原子性问题。原子操作是不可分割的操作。在计算机中,指的是不会被线程调度打断的操作。当一个程序去I/O设备读取数据时,由于I/O设备数据存储和读取的速度,与CPU的执行速度相比,日子就像年。这么厉害又贵的宝贝,怎么能让他休息?,你必须让它一直工作才能切换到执行其他程序。即对CPU的时间进行切片,每个程序在CPU上轮流执行。但是,被剥夺了执行权的程序,从IO中读取数据后,还是要让CPU继续执行。这时候就需要一个数据结构来保存它,以便后面恢复执行。这就是过程。一开始,流程中只有一个“执行流”,只有一个人在干活。随着任务越来越多,发现进程不够用,往往会导致整个程序卡死。这时候计算机允许进程有多个执行流程,工作的人多了,程序就不会再阻塞了。“执行流程”是线程。如何解决这三个问题,是并发和多线程需要处理的。当然,这是后话了。参考资料:《深入理解计算机系统》《计算机组成原理》《计算机组成原理》--唐硕飞https://zhuanlan.zhihu.com/p/379947484本文转载自微信公众号《小牛葫芦露》,作者“小牛葫芦露”,可以使用以下二维码代码重点。
