重学计算机组成原理(二)- 制定学习路线,攀登“性能”之巅

0 学习路线的知识点概括

学习计算机组成原理,就是学习计算机是如何协调运行的

  • 计算机组成原理的英文叫Computer Organization

Organization 意"组织机构"。

该组织机构能够进行各种计算、控制、读取输入,进行输出,达成各种强大的功能。

把整个计算机组成原理的知识点拆分成了四大部分

  • 计算机的基本组成
  • 计算机的指令和计算
  • 处理器设计
  • 存储器和I/O设备。

0.1 计算机的基本组成

计算机的硬件组成

这些硬件,怎么对应到经典的冯·诺依曼体系结构的

除此之外,还需要了解计算机的两个核心指标

  • 性能
  • 功耗

性能和功耗也是我们在应用和设计五大基本组件中需要重点考虑的因素。

0.2 计算机的指令和计算

需要搞明白,我们每天撰写的一行行C、Java、PHP程序,是怎么在计算机里面跑起来的。

  • 了解我们的程序是怎么通过编译器和汇编器,变成一条条机器指令这样的编译过程(编译过程展开,就是编译原理)
  • 知道我们的操作系统是怎么链接、装载、执行这些程序的(深入学习,就是操作系统)。而这一条条指令执行的控制过程,就是由计算机五大组件之一的控制器来控制的。

计算部分,要从二进制和编码开始,理解我们的数据在计算机里的表示,以及我们是怎么从数字电路层面,实现加法、乘法这些基本的运算功能的。

实现这些运算功能的ALU(Arithmetic Logic Unit/ALU),算术逻辑单元,计算机五大组件之一的运算器。

特别重要的就是浮点数(Floating Point)。

浮点数是我们在日常运用中非常容易用错的一种数据表示形式。掌握浮点数能让你对数据的编码、存储和计算能够有一个从表到里的深入理解。尤其在AI火热的今天,浮点数是机器学习中重度使用的数据表示形式,掌握它更是非常有必要。

0.3 CPU的设计

CPU时钟可以用来构造寄存器和内存的锁存器和触发器,因此,CPU时钟应该是我们学习CPU的前导知识。搞明白我们为什么需要CPU时钟(CPU Clock),以及寄存器和内存是用什么样的硬件组成的之后,我们可以再来看看,整个计算机的数据通路是如何构造出来的。

数据通路,其实就是连接了整个运算器和控制器,并最终组成了CPU。而出于对于性能和功耗的考虑,你要进一步理解和掌握面向流水线设计的CPU、数据和控制冒险,以及分支预测的相关技术。

既然CPU作为控制器要和输入输出设备通信,那么我们就要知道异常和中断发生的机制。在CPU设计部分的最后,我会讲一讲指令的并行执行,看看如何直接在CPU层面,通过SIMD来支持并行计算。

0.4 存储器的原理

通过存储器的层次结构作为基础的框架引导,需要掌握从上到下的CPU高速缓存、内存、SSD硬盘和机械硬盘的工作原理,它们之间的性能差异,以及实际应用中利用这些设备会遇到的挑战。存储器其实很多时候又扮演了输入输出设备的角色,所以你需要进一步了解,CPU和这些存储器之间是如何进行通信的,以及我们最重视的性能问题是怎么一回事;理解什么是IO_WAIT,如何通过DMA来提升程序性能。

对于存储器,我们不仅需要它们能够正常工作,还要确保里面的数据不能丢失。于是你要掌握我们是如何通过RAID、Erasure Code、ECC以及分布式HDFS,这些不同的技术,来确保数据的完整性和访问性能。

计算机组成原理的学习办法

相较于整个计算机科学中的其他科目,计算机组成原理更像是整个计算机学科里的“纲要”。这门课里任何一个知识点深入挖下去,都可以变成计算机科学里的一门核心课程。

  • 程序怎样从高级代码变成指令在计算机里面运行,对应着“编译原理”和“操作系统”这两门课程
  • 计算实现背后则是“数字电路”
  • 如果要深入CPU和存储器系统的优化,必然要深入了解“计算机体系结构”。

为了更快更好地学计算机组成,总结了三个学习方法

学会提问自己来串联知识点

学完一个知识点之后,你可以从下面两个方面,问一下自己。

  • 我写的程序,是怎样从输入的代码,变成运行的程序,并得到最终结果的?
  • 整个过程中,计算器层面到底经历了哪些步骤,有哪些地方是可以优化的?

无论是程序的编译、链接、装载和执行,以及计算时需要用到的逻辑电路、ALU,乃至CPU自发为你做的流水线、指令级并行和分支预测,还有对应访问到的硬盘、内存,以及加载到高速缓存中的数据,这些都对应着我们学习中的一个个知识点。建议你自己脑子里过一遍,最好时口头表述一遍或者写下来,这样对你彻底掌握这些知识点都会非常有帮助。

写一些示例程序来验证知识点

计算机科学是一门实践的学科。计算机组成中的大量原理和设计,都对应着“性能”这个词。因此,通过把对应的知识点,变成一个个性能对比的示例代码程序记录下来,是把这些知识点融汇贯通的好方法。因为,相比于强记硬背知识点,一个有着明确性能对比的示例程序,会在你脑海里留下更深刻的印象。当你想要回顾这些知识点的时候,一个程序也更容易提示你把它从脑海深处里面找出来。

通过和计算机硬件发展的历史做对照

计算机的发展并不是一蹴而就的。从第一台电子计算机ENIAC(Electronic Numerical Integrator And Computer,电子数值积分计算机)的发明到现在,已经有70多年了。现代计算机用的各个技术,都是跟随实际应用中遇到的挑战,一个个发明、打磨,最后保留下来的。这当中不仅仅有学术层面的碰撞,更有大量商业层面的交锋。通过了解充满戏剧性和故事性的计算机硬件发展史,让你更容易理解计算机组成中各种原理的由来。

比如说,奔腾4和SPARC的失败,以及ARM的成功,能让我们记住CPU指令集的繁与简、权衡性能和功耗的重要性,而现今高速发展的机器学习和边缘计算,又给计算机硬件设计带来了新的挑战。

学习资料推荐

最有效的办法还是“读书百遍,其义自见”。对于不够明白的知识点,多搜索,多看不同来源的资料,多和朋友、同事、老师一起交流,一定能够帮你掌握好想要学习的知识点。

入门书籍

进阶书籍

拓展阅读

路线学习小结

学习不是死记硬背,学习材料也不是越多越好。

最有效的办法,不是短时间冲刺,而是有节奏地坚持,多在留言区和其他朋友一起交流,就更容易能够“积小步而至千里”,在程序员这个职业上有更长足的发展。

欢迎重学计算机组成原理 ! ! !

  • 买电脑时,“原来的电脑性能跟不上啦”
  • 写程序时,“这个程序性能可以优化一下”

这虚无缥缈的“性能”到底指的是什么呢?

我们能不能给性能下一个明确的定义,然后来进行准确的比较呢?

在计算机组成原理乃至体系结构中,“性能”都是最重要的一个主题。

学习和研究计算机组成原理,就是在理解计算机是怎么运作的,以及为什么要这么运作。

“为什么”所要解决的事情,很多时候就是提升“性能”。

1 时间的倒数 - 性能

计算机的性能,其实和体力劳动很像,好比是我们要搬东西。

对于计算机的性能,我们需要有个标准来衡量。这个标准中主要有两个指标。

1.1 响应时间(Response time)/ 执行时间(Execution time)

让计算机“跑得更快”。

我们执行一个程序,到底需要花多少时间。花的时间越少,自然性能就越好。

  • 实际系统里性能监测工具NewRelic中的响应时间,代表了每个外部的Web请求的执行时间

1.2 吞吐率(Throughput)/ 带宽(Bandwidth)

让计算机“搬得更多”。

服务器使用的网络带宽,通常就是一个吞吐率性能指标.吞吐率是指我们在一定的时间范围内,到底能处理多少事情。这里的“事情”,在计算机里就是处理的数据或者执行的程序指令。

和搬东西对比,如果响应时间短,跑得快,我们可以来回多跑几趟搬几趟。

所以缩短程序的响应时间,一般来说都会提升吞吐率

除了缩短响应时间,我们还有别的方法吗?当然!

我们还可以多找几个人一起来搬,这就类似服务器都是多核的。

人多力量大,同时处理数据,在单位时间内就可以处理更多数据,吞吐率自然也就上去了。

提升吞吐率的办法有很多。大部分时候,我们只要多加一些机器,多堆一些硬件就好了。

但是响应时间的提升却没有那么容易,因为CPU的性能提升其实在10年前就处于“挤牙膏”的状态了,所以我们得慎重地来分析对待。

下面我们具体来看。

我们一般把性能,定义成响应时间的倒数,也就是:

性能 = 1/响应时间

响应时间越短,性能数值越高。

同样一个程序

  • 在Intel最新的CPU Coffee Lake上,只需要30s就能运行完成
  • 而在5年前CPU Sandy Bridge上,需要1min才能完成

那么我们自然可以算出来,Coffee Lake的性能是1/30,Sandy Bridge的性能是1/60,两个的性能比为2。于是,我们就可以说,Coffee Lake的性能是Sandy Bridge的2倍。

过去几年流行的手机跑分软件,就是把多个预设好的程序在手机上运行,然后根据运行需要的时间,算出一个分数来给出手机的性能评估。

而在业界,各大CPU和服务器厂商组织了一个叫作SPEC(Standard Performance Evaluation Corporation)的第三方机构,专门用来指定各种“跑分”的规则

  • 一份SPEC报告通常包含了大量不同测试的评分

SPEC提供的CPU基准测试程序,就好像CPU届的“高考”,通过数十个不同的计算程序,对于CPU的性能给出一个最终评分。

这些程序丰富多彩,有编译器、解释器、视频压缩、人工智能国际象棋等等,涵盖了方方面面的应用场景。感兴趣的话,你可以点击这里

2 计算机的计时单位:CPU时钟

虽然时间是一个很自然的用来衡量性能的指标,但是用时间来衡量时,有两个问题。

2.1 时间的测不准原理

如果用你自己随便写的一个程序,来统计程序运行的时间,每一次统计结果不会完全一样。

为什么会不准呢?这里面有好几个原因。

2.1.1 统计时间方法

我们统计时间是用类似于“掐秒表”一样,记录 程序运行结束时间减去程序开始运行的时间。

这个时间也叫Wall Clock Time或者Elapsed Time

就是在运行程序期间,挂在墙上的钟走掉的时间。

但计算机可能同时运行着好多个程序,CPU实际上不停地在各个程序之间进行切换。

在这些走掉的时间里,很可能CPU切换去运行别的程序了。

而且,有些程序在运行的时候,可能要从网络、硬盘去读取数据,要等网络和硬盘把数据读出来,给到内存和CPU。

要想准确统计某程序的实际运行时间,进而比较程序之间的性能,须把这些额外时间除掉

那这件事怎么实现呢???

Linux下有一个叫time的命令,可助我们一臂之力,同样的Wall Clock Time下,程序实际在CPU上到底花了多少时间。

我们简单运行一下time命令。它会返回三个值

  • 第一个 real time
    也就是我们说的Wall Clock Time,即运行程序整个过程中流逝掉的时间
  • 第二个 user time
    CPU在运行你的程序,在用户态运行指令的时间
  • 第三个sys time
    CPU运行你的程序,在操作系统内核里运行指令的时间

程序实际花费的CPU执行时间(CPU Time),就是user time加上sys time

一般情况下,如果user+sys比real大,甚至仅user比real大的情况出现,都是因为对应的程序被多个进程或者多个线程并行执行了,也很常见。

在多核或者多cpu的机器上运行,seq和wc命令会分配到两个cpu上,user和sys是两个cpu时间相加的,而real只是现实时钟里走过的时间,极端情况下user+sys可以到达real的两倍

虽然seq和wc这两个命令都是单线程运行的,但是这两个命令在多核cpu运行的情况下,会分别分配到两个不同的cpu,于是user和sys的时间都是两个cpu上运行的时间之和,就可能超过real的时间。

可以这样来快速验证,运行

time seq 100000000 | wc -l &

让这个命令多跑一会儿,并且在后台运行。

然后利用 top 命令看不同进程的cpu占用情况

你会在top的前几行里看到seq和wc的cpu占用都接近100,实际是各被分配到了一个不同的cpu执行。

2.1.2 不一定可直接比较出性能

即使我们已经拿到了CPU时间,我们也不一定可以直接“比较”出两个程序的性能差异

即使在同一台计算机上,CPU可能满载运行也可能降频运行,降频运行的时候自然花的时间会多一些。

除CPU外,时间这个性能指标还会受到主板、内存这些其他相关硬件的影响。

所以,我们需要对“时间”这个我们可以感知的指标进行

2.2 CPU时间拆解

程序的CPU执行时间=CPU时钟周期数×时钟周期时间
  • 时钟周期时间
    你在买电脑的时候,一定关注过CPU的主频
    我手头的这台电脑就是
  • 2.8 GHz Intel Core i7

这里的2.8GHz就是电脑的主频(Frequency/Clock Rate)。

这个2.8GHz,我们可以先简单地理解为,CPU在1秒时间内,可以执行的简单指令的数量是2.8G条。

更准确点,这个2.8GHz就代表,我们CPU的一个“钟表”能够识别出来的最小的时间间隔。

就像我们挂在墙上的挂钟,都是一秒一秒地走,所以通过墙上的挂钟能够识别出来的最小时间单位就是秒。

而在CPU内部,有一个叫晶体振荡器(Oscillator Crystal)的东西,简称为晶振。

把晶振当成CPU内部的电子表来使用。

晶振带来的每一次“滴答”,就是时钟周期时间。

在我这个2.8GHz的CPU上,这个时钟周期时间,就是1/2.8G。

我们的CPU,是按照这个“时钟”提示的时间来进行自己的操作。

主频越高,意味着这个表走得越快,我们的CPU也就走得越快。

“超频”,这说的其实就相当于把买回来的CPU内部的钟给调快了,于是CPU的计算跟着这个时钟的节奏,也就自然变快了。当然这个快不是没有代价的,CPU跑得越快,散热的压力也就越大。就和人一样,超过生理极限,CPU就会崩溃了。

  • 回顾之前的CPU执行时间的公式程序的CPU执行时间=CPU时钟周期数×时钟周期时间

最简单的提升性能方案,自然缩短时钟周期时间,也就是提升主频。

换句话说,就是换一块好一点的CPU。

不过,这个是我们这些底层的研发人员控制不了的,所以我们就把目光挪到了乘法的另一个因子——CPU时钟周期数上。

如果能够减少程序需要的CPU时钟周期数量,一样能够提升程序性能。

  • 对于CPU时钟周期数,我们可以再做一个分解,把它变成CPU时钟周期数 = 指令数×每条指令的平均时钟周期数(Cycles Per Instruction,简称CPI)不同的指令需要的Cycles是不同的
    加法和乘法都对应着一条CPU指令
    但是乘法需要的Cycles就比加法要多,自然也就慢。
    在这样拆分了之后,我们的程序的CPU执行时间就可以变成这样三个部分的乘积。
程序的CPU执行时间=指令数 × CPI × Clock Cycle Time

因此,要解决性能问题,就是要优化这三者。

  • 时钟周期时间
    就是计算机主频,取决于硬件。摩尔定律就一直在不停提高的主频。
    最早的80386主频只有33MHz,现在手头的笔记本电脑就有2.8GHz,在主频层面,就提升了将近100倍。
  • 每条指令的平均时钟周期数CPI
    一条指令到底需要多少CPU Cycle。在后面讲解CPU结构的时候,我们会看到,现代的CPU通过流水线技术(Pipeline),让一条指令需要的CPU Cycle尽可能地少。因此,对于CPI的优化,也是计算机组成和体系结构中的重要一环。
  • 指令数
    代表执行我们的程序到底需要多少条指令、用哪些指令。
    这个很多时候就把挑战交给了编译器。
    同样的代码,编译成计算机指令时候,就有各种不同的表示方式。

把自己想象成一个CPU,坐在那里写程序。
计算机主频就好像是你的打字速度,打字越快,你自然可以多写一点程序。

CPI相当于你在写程序的时候,熟悉各种快捷键,越是打同样的内容,需要敲击键盘的次数就越少。

指令数相当于你的程序设计得够合理,同样的程序要写的代码行数就少。

如果三者皆能实现,你自然可以很快地写出一个优秀的程序,“性能”从外面来看就是好的。

3 总结

学完本文,对“性能”这个名词,你应该有了更清晰的认识。

主要对于“响应时间”这个性能指标进行抽丝剥茧,拆解成了计算机时钟周期、CPI以及指令数这三个独立的指标的乘积,并且为指明了优化计算机性能的三条康庄大道。

也就是,提升计算机主频,优化CPU设计使得在单个时钟周期内能够执行更多指令,以及通过编译器来减少需要的指令数。

后面会讲解,具体怎么在电路硬件、CPU设计,乃至指令设计层面,提升计算机的性能。

参考

原文地址:https://www.cnblogs.com/JavaEdge/p/11332685.html

时间: 2024-10-27 06:10:23

重学计算机组成原理(二)- 制定学习路线,攀登“性能”之巅的相关文章

重学计算机组成原理(九)- 动态链接

把对应的不同文件内的代码段,合并到一起,成为最后的可执行文件 链接的方式,让我们在写代码的时候做到了"复用". 同样的功能代码只要写一次,然后提供给很多不同的程序进行链接就行了. "链接"其实有点儿像我们日常生活中的标准化.模块化生产. 有一个可以生产标准螺帽的生产线,就可生产很多不同的螺帽. 只要需要螺帽,都可以通过链接的方式,去复制一个出来,放到需要的地方 但是,如果我们有很多个程序都要通过装载器装载到内存里面,那里面链接好的同样的功能代码,也都需要再装载一遍,

重学计算机组成原理(十)- "烫烫烫"乱码的由来

程序 = 算法 + 数据结构 对应到计算机的组成原理(硬件层面) 算法 --- 各种计算机指令 数据结构 --- 二进制数据 计算机用0/1组成的二进制,来表示所有信息 程序指令用到的机器码,是使用二进制表示的 存储在内存里面的字符串.整数.浮点数也都是用二进制表示的 万物在计算机里都是0和1,搞清楚各种数据在二进制层面是怎么表示的,是我们的必修课. 在实际应用中最常遇到的问题,也就是文本字符串是怎么表示成二进制的,特别是我们会遇到的乱码究竟是怎么回事儿 在开发的时候,所说的Unicode和UT

重学计算机组成原理(六)- 函数调用怎么突然Stack Overflow了!

用Google搜异常信息,肯定都访问过Stack Overflow网站 全球最大的程序员问答网站,名字来自于一个常见的报错,就是栈溢出(stack overflow) 从函数调用开始,在计算机指令层面函数间的相互调用是怎么实现的,以及什么情况下会发生栈溢出 1 栈的意义 先看一个简单的C程序 function.c 直接在Linux中使用GCC编译运行 [[email protected] Documents]$ vim function.c [[email protected] Document

重学计算机组成原理(十一)- 门电路的"千里传音"

人用纸和笔来做运算,都是用十进制,直接用十进制和我们最熟悉的符号不是最简单么? 为什么计算机里我们最终要选择二进制呢? 来看看,计算机在硬件层面究竟是怎么表示二进制的,你就会明白,为什么计算机会选择二进制. 1 怎么做到"千里传书" 马拉松的故事相信你听说过.公元前490年,在雅典附近的马拉松海边,发生了波斯和希腊之间的希波战争.雅典和斯巴达领导的希腊联军胜利之后,雅典飞毛腿菲迪皮德斯跑了历史上第一个马拉松,回雅典报喜.这个时候,人们在远距离报信的时候,采用的是派人跑腿,传口信或者送信

2019我要学软测:软件测试学习路线

软件测试好学么?软件测试学习路线如下: 你要具备软件测试常识.软件测试行业就像一个围城,很多围城外的人想要进来,一没有高人指点,领你进去:二没有人借梯子给你让你走进去.所以说,如果你是跨专业或者是换职业来做软件测试工程师,是难度非常大的! 所以作为小白,如何入行?那么这个就是我们今天要做的. 第一步:具备软件测试常识. 1)什么是软件测试 2)软件测试的分类 3)软件测试常用的一些用例设计方法 4)如何做需求分析 5)如何写软件测试用例 6)什么是bug&bug的管理工具 7)软件测试计划&

云计算应该怎么学?云计算高端学习路线

云计算是分布式计算.并行计算.效用计算.网络存储.虚拟化.负载均衡.热备份冗余等传统计算机和网络技术发展融合的产物.零基础学习云计算,云计算学习如何入门?近年来Linux云计算已经越来越受到重用,它不再仅仅是一些开源发烧友们之间炫耀资本,而且已经在多方面价值得到了体现,尤其在服务器操作系统方面,已经成为资深运维工程师的首选的操作工具.那么该如何学习云计算呢?接下来就简单的聊一聊云计算的基础阶段(初级运维工程师). 作为一个新手要想入门云计算,那么在初级阶段需要把linux学习路线搞清楚,任何学习

优秀的云计算工程师需要学什么?云计算Docker学习路线

云计算工程师要学什么?随着互联网的快速发展,云计算这个词大家并不陌生,但是云计算究竟是做什么的,想要从事云计算要学习什么,很多都不知道,那么今天就给大家讲一下云计算. 云计算是基于互联网的相关服务的增加.使用和交付模式,通常涉及通过互联网来提供动态易扩展且经常是虚拟化的资源.云是网络.互联网的一种比喻说法.过去在图中往往用云来表示电信网,后来也用来表示互联网和底层基础设施的抽象.因此,云计算甚至可以让你体验每秒10万亿次的运算能力,拥有这么强大的计算能力可以模拟核爆炸.预测气候变化和市场发展趋势

【重学计算机】机组D8章:输入输出系统

1. 输入输出系统概述 组成:外设.接口.总线.管理软件 基本功能 完成计算机内外的信息传递 保证CPU正确选择输出设备 利用缓冲等,实现主机与外设的速度匹配 特点:异步性.实时性.设备无关性 输入过程:CPU把地址值放入总线 --> CPU等候设备数据有效 --> CPU从总线读入数据存入寄存器 输出过程:CPU把地址值放入总线 --> CPU把数据值放入总线 --> 设备等数据有效取走数据 IO系统性能:存储IO.通信IO 连接特性:哪些设备可以和IO相连 IO系统容量:IO系

嵌入式开发要学什么_必备嵌入式学习路线_高手速成方法

最近遇到很多处于迷茫中的新手,在纠结要不要去学嵌入式,主要问题在于嵌入式的门槛非常高,经验少.或者非电子专业投身嵌入式行业能否发展下去.学习嵌入式可以说是比较困难的,但是也是有方法的,要增加自己Linux的技能,只有通过实践来实现了.所以,一定要在学习中勤于实践,你会收获更多. 在实际的学习过程中,嵌入式软件工程师需要学什么?相信是困扰所有嵌入式初学者的难题,大致可以总结为:嵌入式首先懂得熟悉C语言,而后可以从系统编程入手,再深入到裸机开发.系统移植.驱动开发等.嵌入式需要懂得的一些基本诸如Li