![](https://img-blog.csdnimg.cn/20201014180756919.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
读书日记
文章平均质量分 87
记录自己读书的日记
Polarisy丶
这个作者很懒,什么都没留下…
展开
-
深入浅出计算机组成原理26-Superscalar和VLIW:如何让CPU的吞吐率超过1?
我们先回顾一下第 4 讲,不知道你是否还记得这个公式:程序的 CPU 执行时间 = 指令数 × CPI × Clock Cycle Time这个公式里,有一个叫 CPI 的指标。我们知道,CPI 的倒数,又叫作 IPC(Instruction Per Clock),也就是一个时钟周期里面能够执行的指令数,代表了 CPU 的吞吐率。那么,这个指标,放在我们前面几节反复优化流水线架构的 CPU 里,能达到多少呢?答案是,最佳情况下,IPC 也只能到 1。原创 2022-10-12 14:16:44 · 438 阅读 · 0 评论 -
深入浅出计算机组成原理25-冒险和预测(四):今天下雨了,明天还会下雨么?
好了,这一讲,我给你讲解了什么是控制冒险,以及应对控制冒险的三个方式。第一种方案,类似我们的操作数前推,其实是在改造我们的 CPU 功能,通过增加对应的电路的方式,来缩短分支带来的延迟。另外两种解决方案,无论是“假装分支不发生”,还是“动态分支预测”,其实都是在进行“分支预测”。只是,“假装分支不发生”是一种简单的静态预测方案而已。在动态分支预测技术里,我给你介绍了一级分支预测,或者叫 1 比特饱和计数的方法。其实就是认为,预测结果和上一次的条件跳转是一致的。原创 2022-10-11 14:55:18 · 188 阅读 · 0 评论 -
深入浅出计算机组成原理24-冒险和预测(三):CPU里的“线程池”
好了,总结一下。这一讲里,我为你介绍了乱序执行,这个解决流水线阻塞的技术方案。因为数据的依赖关系和指令先后执行的顺序问题,很多时候,流水线不得不“阻塞”在特定的指令上。即使后续别的指令,并不依赖正在执行的指令和阻塞的指令,也不能继续执行。而乱序执行,则是在指令执行的阶段通过一个类似线程池的保留站,让系统自己去动态调度先执行哪些指令。这个动态调度巧妙地解决了流水线阻塞的问题。指令执行的先后顺序,不再和它们在程序中的顺序有关。我们只要保证不破坏数据依赖就好了。原创 2022-10-11 14:34:29 · 167 阅读 · 0 评论 -
深入浅出计算机组成原理23-冒险和预测(二):流水线里的接力赛
这一讲,我给你介绍了一个更加高级,也更加复杂的解决数据冒险问题方案,就是操作数前推,或者叫操作数旁路。操作数前推,就是通过在硬件层面制造一条旁路,让一条指令的计算结果,可以直接传输给下一条指令,而不再需要“指令 1 写回寄存器,指令 2 再读取寄存器“这样多此一举的操作。这样直接传输带来的好处就是,后面的指令可以减少,甚至消除原本需要通过流水线停顿,才能解决的数据冒险问题。这个前推的解决方案,不仅可以单独使用,还可以和前面讲解过的流水线冒泡结合在一起使用。原创 2022-10-11 14:15:54 · 555 阅读 · 0 评论 -
深入浅出计算机组成原理22-冒险和预测(一):hazard是“危”也是“机”
讲到这里,相信你已经弄明白了什么是结构冒险,什么是数据冒险,以及数据冒险所要保障的三种依赖,也就是数据依赖、反依赖以及输出依赖。一方面,我们可以通过增加资源来解决结构冒险问题。我们现代的 CPU 的体系结构,其实也是在冯·诺依曼体系结构下,借鉴哈佛结构的一个混合结构的解决方案。我们的内存虽然没有按照功能拆分,但是在高速缓存层面进行了拆分,也就是拆分成指令缓存和数据缓存这样的方式,从硬件层面,使得同一个时钟下对于相同资源的竞争不再发生。原创 2022-10-11 11:25:07 · 784 阅读 · 0 评论 -
深入浅出计算机组成原理21-面向流水线的指令设计(下):奔腾4是怎么失败的?
相信到这里,你对 CPU 的流水线技术,有了一个更加深入的了解。你会发现,流水线技术和其他技术一样,都讲究一个“折衷”(Trade-Off)。一个合理的流水线深度,会提升我们 CPU 执行计算机指令的吞吐率。我们一般用 IPC(Instruction Per Cycle)来衡量 CPU 执行指令的效率。IPC 呢,其实就是我们之前在第 3 讲讲的 CPI(Cycle Per Instruction)的倒数。也就是说, IPC = 3 对应着 CPI = 0.33。原创 2022-10-10 19:41:13 · 201 阅读 · 0 评论 -
深入浅出计算机组成原理20-面向流水线的指令设计(上):一心多用的现代CPU
讲到这里,相信你已经能够理解,为什么我们的 CPU 需要流水线设计了,也能把每一个流水线阶段在干什么,和上一讲的整个 CPU 的数据通路的连接过程对上了。可以看到,为了能够不浪费 CPU 的性能,我们通过把指令的执行过程,切分成一个一个流水线级,来提升 CPU 的吞吐率。而我们本身的 CPU 的设计,又是由一个个独立的组合逻辑电路串接起来形成的,天然能够适合这样采用流水线“专业分工”的工作方式。因为每一级的 overhead,一味地增加流水线深度,并不能无限地提高性能。原创 2022-10-10 11:30:55 · 191 阅读 · 0 评论 -
深入浅出计算机组成原理19-建立数据通路(下):指令+运算=CPU
好了,今天我们讲完了,怎么通过连接不同功能的电路,实现出一个完整的 CPU。我们可以通过自动计数器的电路,来实现一个 PC 寄存器,不断生成下一条要执行的计算机指令的内存地址。然后通过译码器,从内存里面读出对应的指令,写入到 D 触发器实现的指令寄存器中。再通过另外一个译码器,把它解析成我们需要执行的指令和操作数的地址。这些电路,组成了我们计算机五大组成部分里面的控制器。原创 2022-10-09 15:52:40 · 218 阅读 · 0 评论 -
深入浅出计算机组成原理18-建立数据通路(中):指令+运算=CPU
好了,到了这里,我们可以顺一顺思路了。通过引入了时序电路,我们终于可以把数据“存储”下来了。我们通过反馈电路,创建了时钟信号,然后再利用这个时钟信号和门电路组合,实现了“状态记忆”的功能。电路的输出信号不单单取决于当前的输入信号,还要取决于输出信号之前的状态。最常见的这个电路就是我们的 D 触发器,它也是我们实际在 CPU 内实现存储功能的寄存器的实现方式。原创 2022-10-09 15:06:12 · 159 阅读 · 0 评论 -
深入浅出计算机组成原理17-建立数据通路(上):指令+运算=CPU
好了,到这里,我们已经把 CPU 运转需要的数据通路和控制器介绍完了,也找出了需要完成这些功能,需要的 4 种基本电路。它们分别是,ALU 这样的组合逻辑电路、用来存储数据的锁存器和 D 触发器电路、用来实现 PC 寄存器的计数器电路,以及用来解码和寻址的译码器电路。虽然 CPU 已经是由几十亿个晶体管组成的及其复杂的电路,但是它仍然是由这样一个个基本功能的电路组成的。只要搞清楚这些电路的运作原理,你自然也就弄明白了 CPU 的工作原理。原创 2022-10-09 14:47:04 · 440 阅读 · 0 评论 -
深入浅出计算机组成原理16-浮点数和定点数(下):深入理解浮点数到底有什么用?
到这里,我们已经讲完了浮点数的表示、加法计算以及可能会遇到的精度损失问题。可以看到,虽然浮点数能够表示的数据范围变大了很多,但是在实际应用的时候,由于存在精度损失,会导致加法的结果和我们的预期不同,乃至于完全没有加上的情况。所以,一般情况下,在实践应用中,对于需要精确数值的,比如银行存款、电商交易,我们都会使用定点数或者整数类型。比方说,你一定在 MySQL 里用过 decimal(12,2),来表示订单金额。原创 2022-09-30 16:50:48 · 172 阅读 · 0 评论 -
深入浅出计算机组成原理15-浮点数和定点数(上):怎么用有限的Bit表示尽可能多的信息?
你会看到,在这样的表示方式下,浮点数能够表示的数据范围一下子大了很多。正是因为这个数对应的小数点的位置是“浮动”的,它才被称为浮点数。随着指数位 e 的值的不同,小数点的位置也在变动。对应的,前面的 BCD 编码的实数,就是小数点固定在某一位的方式,我们也就把它称为定点数。回到我们最开头,为什么我们用 0.3 + 0.6 不能得到 0.9 呢?这是因为,浮点数没有办法精确表示 0.3、0.6 和 0.9。原创 2022-09-30 16:28:36 · 122 阅读 · 0 评论 -
深入浅出计算机组成原理14-乘法器:如何像搭乐高一样搭电路(下)?
通过精巧地设计电路,用较少的门电路和寄存器,就能够计算完成乘法这样相对复杂的运算。是用更少更简单的电路,但是需要更长的门延迟和时钟周期;还是用更复杂的电路,但是更短的门延迟和时钟周期来计算一个复杂的指令,这之间的权衡,其实就是计算机体系结构中 RISC 和 CISC 的经典历史路线之争。原创 2022-09-30 14:28:57 · 397 阅读 · 0 评论 -
深入浅出计算机组成原理13-加法器:如何像搭乐高一样搭电路(上)?
相信到这里,你应该已经体会到了,通过门电路来搭建算术计算的一个小功能,就好像搭乐高积木一样。我们用两个门电路,搭出一个半加器,就好像我们拿两块乐高,叠在一起,变成一个长方形的乐高,这样我们就有了一个新的积木组件,柱子。我们再用两个柱子和一个长条的积木组合一下,就变成一个积木桥。然后几个积木桥串接在一起,又成了积木楼梯。当我们想要搭建一个摩天大楼,我们需要很多很多楼梯。但是这个时候,我们已经不再关注最基础的一节楼梯是怎么用一块块积木搭建起来的。这其实就是计算机中,无论软件还是硬件中一个很重要的设计思想,原创 2022-09-29 17:15:52 · 225 阅读 · 0 评论 -
深入浅出计算机组成原理12-理解电路:从电报机到门电路,我们如何做到“千里传信”?
可以说,电报是现代计算机的一个最简单的原型。它和我们现在使用的现代计算机有很多相似之处。我们通过电路的“开”和“关”,来表示“1”和“0”。就像晶体管在不同的情况下,表现为导电的“1”和绝缘的“0”的状态。我们通过电报机这个设备,看到了如何通过“螺旋线圈 + 开关”,来构造基本的逻辑电路,我们也叫门电路。一方面,我们可以通过继电器或者中继,进行长距离的信号传输。另一方面,我们也可以通过设置不同的线路和开关状态,实现更多不同的信号表示和处理方式,这些线路的连接方式其实就是我们在数字电路中所说的门电路。原创 2022-09-28 17:17:06 · 588 阅读 · 0 评论 -
深入浅出计算机组成原理11-二进制编码:“手持两把锟斤拷,口中疾呼烫烫烫”?
众所周知,现代计算机都是用 0 和 1 组成的二进制,来表示所有的信息。前面几讲的程序指令用到的机器码,也是使用二进制表示的;我们存储在内存里面的字符串、整数、浮点数也都是用二进制表示的。万事万物在计算机里都是 0 和 1,所以呢,搞清楚各种数据在二进制层面是怎么表示的,是我们必备的一课。然后呢,我们重点来看一看,大家在实际应用中最常遇到的问题,也就是文本字符串是怎么表示成二进制的,特别是我们会遇到的乱码究竟是怎么回事儿。我们平时在开发的时候,所说的 Unicode 和 UTF-8 之间有什么关系。原创 2022-09-27 16:16:21 · 235 阅读 · 0 评论 -
深入浅出计算机组成原理10-动态链接:程序内部的“共享单车”
我们上一节解决程序装载到内存的时候,讲了很多方法。说起来,最根本的问题其实就是内存空间不够用。如果我们能够让同样功能的代码,在不同的程序里面,不需要各占一份内存空间,那该有多好啊!这个思路就引入一种新的链接方法,叫作相应的,我们之前说的合并代码段的方法,就是在动态链接的过程中,我们想要“链接”的,不是存储在硬盘上的目标文件代码,而是加载到内存中的顾名思义,这里的共享库重在“共享“这两个字。这个加载到内存中的共享库会被很多个程序的指令调用到。原创 2022-09-27 14:32:15 · 82 阅读 · 0 评论 -
深入浅出计算机组成原理09-程序装载:“640K内存”真的不够用么?
用虚拟内存解决进程间隔离, 用分段技术解决物理地址不连续的问题,用内存交换解决内存碎片问题,用分页来解决分段情况下的内存交换很耗性能的问题。原创 2022-09-27 11:20:17 · 111 阅读 · 0 评论 -
深入浅出计算机组成原理08-ELF和静态链接:为什么程序无法同时在Linux和Windows下运行?
讲到这里,相信你已经猜到,为什么同样一个程序,在 Linux 下可以执行而在 Windows 下不能执行了。其中一个非常重要的原因就是,两个操作系统下可执行文件的格式不一样。我们今天讲的是 Linux 下的 ELF 文件格式,而 Windows 的可执行文件格式是一种叫作PE(Portable Executable Format)的文件格式。Linux 下的装载器只能解析 ELF 格式而不能解析 PE 格式。原创 2022-09-22 20:39:38 · 85 阅读 · 0 评论 -
深入浅出计算机组成原理07-函数调用:为什么会发生stack overflow?
然后,我们可以调用第 13 行的 ret 指令,这时候同时要把 call 调用的时候压入的 PC 寄存器里的下一条指令出栈,更新到 PC 寄存器中,将程序的控制权返回到出栈后的栈顶。你可以把调用的函数指令,直接插入在调用函数的地方,替换掉对应的 call 指令,然后在编译器编译代码的时候,直接就把函数调用变成对应的指令替换掉。它们两个都是在原来顺序执行的指令过程里,执行了一个内存地址的跳转指令,让指令从原来顺序执行的过程里跳开,从新的跳转后的位置开始执行。call 指令后面跟着的,仍然是跳转后的程序地址。原创 2022-09-21 14:19:46 · 79 阅读 · 0 评论 -
深入浅出计算机组成原理06-指令跳转:原来if...else就是goto
这一节,我们在单条指令的基础上,学习了程序里的多条指令,究竟是怎么样一条一条被执行的。除了简单地通过 PC 寄存器自增的方式顺序执行外,条件码寄存器会记录下当前执行指令的条件判断状态,然后通过跳转指令读取对应的条件码,修改 PC 寄存器内的下一条指令的地址,最终实现 if…else 以及 for/while 这样的程序控制流程。原创 2022-09-20 19:58:33 · 236 阅读 · 0 评论 -
深入浅出计算机组成原理05-计算机指令:让我们试试用纸带编程
为什么早期的计算机程序要使用打孔卡,而不能像我们现在一样,用 C 或者 Python 这样的高级语言来写呢?原因很简单,因为计算机或者说 CPU 本身,并没有能力理解这些高级语言。即使在 2022 年的今天,我们使用的现代个人计算机,仍然只能处理所谓的“机器码”,也就是一连串的“0”和“1”这样的数字。那么,我们每天用高级语言的程序,最终是怎么变成一串串“0”和“1”的?这一串串“0”和“1”又是怎么在 CPU 中处理的?今天,我们就来仔细介绍一下,“机器码”和“计算机指令”到底是怎么回事。原创 2022-09-20 17:44:21 · 245 阅读 · 0 评论 -
深入浅出计算机组成原理04-穿越功耗墙,我们该从哪些方面提升“性能”?
我们可以看到,无论是简单地通过提升主频,还是增加更多的 CPU 核心数量,通过并行来提升性能,都会遇到相应的瓶颈。仅仅简单地通过“堆硬件”的方式,在今天已经不能很好地满足我们对于程序性能的期望了。于是,工程师们需要从其他方面开始下功夫了。在“摩尔定律”和“并行计算”之外,在整个计算机组成层面,还有这样几个原则性的性能提升方法。原创 2022-09-19 15:19:26 · 230 阅读 · 0 评论 -
深入浅出计算机组成原理03-通过你的CPU主频,我们来谈谈“性能”究竟是什么?
优化计算机性能三条大道,提升计算机主频,优化 CPU 设计使得在单个时钟周期内能够执行更多指令,以及通过编译器来减少需要的指令数。原创 2022-09-19 10:52:25 · 185 阅读 · 0 评论 -
深入浅出计算机组成原理02-计算机组成原理应该这么学
计算机组成原理的英文叫 Computer Organization。这里的 Organization 是“组织机构”的意思。计算机由很多个不同的部件放在一起,变成了一个“组织机构”。这个组织机构最终能够进行各种计算、控制、读取输入,进行输出,达成各种强大的功能。整个计算机组成原理的知识点被拆分成了四大部分,分别是计算机的基本组成、计算机的指令和计算、处理器设计,以及存储器和 I/O 设备。原创 2022-09-16 17:01:40 · 229 阅读 · 0 评论 -
深入浅出计算机组成原理01-冯·诺依曼体系结构
冯·诺依曼体系结构确立了我们现在每天使用的计算机硬件的基础架构。因此,学习计算机组成原理,其实就是学习和拆解冯·诺依曼体系结构。具体来说,学习组成原理,其实就是学习控制器、运算器的工作原理,也就是 CPU 是怎么工作的,以及为何这样设计;学习内存的工作原理,从最基本的电路,到上层抽象给到 CPU 乃至应用程序的接口是怎样的;学习 CPU 是怎么和输入设备、输出设备打交道的。原创 2022-09-16 15:55:44 · 567 阅读 · 0 评论