计算机组成原理

深入浅出计算机组成原理:理解Disruptor(下)-不需要换挡和踩刹⻋的CPU,有多快?(第55讲)

眉间皱痕 提交于 2019-11-29 17:31:08
一、引子 上一讲,我们学习了一个精妙的想法,Disruptor通过缓存行填充,来利用好CPU的高速缓存。不知道你做完课后思考题之后,有没有体会到高速缓存在实践中带来的速度提升呢? 不过,利用CPU高速缓存,只是Disruptor“快”的一个因素,那今天我们就来看一看Disruptor快的另一个因素,也就是“无锁”,而尽可能发挥CPU本身的高速处理性能。 二、缓慢的锁 Disruptor作为一个高性能的生产者-消费者队列系统,一个核心的设计就是通过RingBuffer实现一个无锁队列。 上一讲里我们讲过,Java里面的基础库里,就有像LinkedBlockingQueue这样的队列库。但是,这个队列库比起Disruptor利用的RingBuffer要慢上很多。慢的第益个原因我们说过, 因为链表的数据在内存里面的布局对于高速缓存并不友好,而RingBuffer所使用的数组则不然。 LinkedBlockingQueue慢,有另外一个重要的因素,那就是它对于锁的依赖。在生产者-消费者模式里,我们可能有多个消费者,同样也可能有多个生产者。多个生产者都要往队列的尾指针里面添加新的任务, 就会产生多个线程的竞争。于是,在做这个事情的时候,生产者就需要拿到对于队列尾部的锁。同样地,在多个消费者去消费队列头的时候,也就产生竞争。同样消费者也要拿到锁。 那只有意个生产者,或者一个消费者

深入浅出计算机组成原理:设计⼤型DMP系统(下)-SSD拯救了所有的DBA(第53讲)

怎甘沉沦 提交于 2019-11-29 13:10:12
一、上节总结回顾 上一讲里,根据DMP系统的各个应用场景,我们从抽象的原理层面,选择了AeroSpike作为KV数据库,Kafka作为数据管道,Hadoop/Hive来作为数据仓库。 不过呢,肯定有不信邪的工程师会问,为什么MongoDB,甚至是MySQL这样的文档数据库或者传统的关系型数据库不适应呢?为什么不能通过优化SQL、添加缓存这样的调优手段,解决这个问题呢? 今天DMP的下半场,我们就从数据库实现的原理,一起来看一看,这背后的原因。如果你能弄明表今天的这些更深入、更细节的原理,对于什么场景使用什么数据库,就会更加胸有成竹,而不是只有 跑了大量的性能测试才知道。下次做数据库选型的时候,你就可以“以理服人”了。 二、关系型数据库:不得不做的随机读写 我们先来想一想,如果现在让你自己写一个最简单的关系型数据库,你的数据要怎么存放在硬盘上?最简单最直观的想法是, 1、你的数据要怎么存放在硬盘上? 1、用一个CSV文件格式。一个文件就是一个数据表。 2、文件里面的每一行就是这个表里面的一条记录。 3、如果要修改数据库里面的某一条记录,那么我们要先找到这记录, 4、然后直接去修改这一行的数据。读取数据也是一样的。 要找到这样数据,最笨的办法当然是一行一行读,也就是遍历整个CSV文件。 不过这样的话,相当于随便读取任何一条数据都要扫描全表 , 2、太浪费硬盘的吞吐量了。那怎么办呢?

深入浅出计算机组成原理:Superscalar和VLIW-如何让CPU的吞吐率超过1?(第26讲)

不想你离开。 提交于 2019-11-29 03:10:51
一、引子 到今天为止,专栏已经过半了。过去的20多讲里,我给你讲的内容,很多都是围绕着怎么提升CPU的性能这个问题展开的。我们先回顾一下第4讲,不知道你是否还记得这个公式: 程序的CPU执行时间 = 指令数 × CPI × Clock Cycle Time 这个公式里,有一个叫CPI的指标。我们知道,CPI的倒数,又叫作IPC(Instruction Per Clock),也就是一个时钟周期里面能够执行的指令数,代表了CPU的吞吐率。那么,这个指标,放在我们前面几节反复优化流 水线架构的CPU里,能达到多少呢? 答案是,最佳情况下,IPC也只能到1。因为无论做了哪些流水线层面的优化,即使做到了指令执行层面的乱 这说明,无论指令后续能优化得多好,一个时钟周期也只能执行完这样一条指令,CPI只能是1。但是,我们现在用的Intel CPU或者ARM的CPU,一般的CPI都能做到2以上,这是怎么做到的呢? 今天,我们就一起来看看,现代CPU都使用了什么 “黑科技”。 二、多发射与超标量:同一实践执行的两条指令 1、整数和浮点数计算的电路,在CPU层面也是分开的 之前讲CPU的硬件组成的时候,我们把所有算术和逻辑运算都抽象出来,变成了一个ALU这样的“黑盒子”。你应该还记得第13讲到第16讲,关于加法器、乘法器、乃至浮点数计算的部分,其实整数的计算和 浮点数的计算过程差异还是不小的。实际上

深入浅出计算机组成原理:冒险和预测(二)-流水线里的接力赛(第23讲)

岁酱吖の 提交于 2019-11-29 02:35:34
一、引子 1、解决不同指令之间的数据依赖问题。 上一讲,我为你讲解了结构冒险和数据冒险,以及应对这两种冒险的两个解决方案。一种方案是增加资源,通过添加指令缓存和数据缓存,让我们对于指令和数据的访问可以同时进行。 这个办法帮助CPU解决了取指令和访问数据之间的资源冲突。另一种方案是直接进行等待。通过插入NOP这样的无效指令,等待之前的指令完成。这样我们就能解决不同指令之间的数据依赖问题 2、上一讲的这两种方案这两种方案都有点儿笨。 着急的人,看完上一讲的这两种方案,可能已经要跳起来问了:“这也能算解决方案么?”的确,这两种方案都有点儿笨。 第一种解决方案,好比是在软件开发的过程中,发现效率不够,于是研发负责人说:“ 我们需要双倍的人手和研发资源 。”而第二种解决方案,好比你在提需求的时候,研发负责人告诉你说: “来不及做,你只能等 我们需求排期。” 你应该很清楚地知道,“堆资源”和“等排期”这样的解决方案,并不会真的提高我们的效率,只是避免冲突的无奈之举。 那针对流水线冒险的问题,我们有没有更高级或者更高效的解决方案呢?既不用简单花钱加硬件电路这样 “堆资源” ,也不是纯粹等待之前的任务完成这样 “等排期” 。 答案当然是有的。这一讲,我们就来看看计算机组成原理中,一个更加精巧的解决方案, 操作数前推 二、NOP操作和指令对齐 要想理解操作数前推技术,我们先来回顾一下,第5讲讲过的

深入浅出计算机组成原理:冒险和预测(四)-今天下雨了,明天还会下雨么?(第24讲)

让人想犯罪 __ 提交于 2019-11-29 01:47:32
一、引子 1、取指令(IF)和指令译码(ID)的阶段,是不需要停顿的 过去三讲,我主要为你介绍了结构冒险和数据冒险,以及增加资源、流水线停顿、操作数前推、乱序执行,这些解决各种“冒险”的技术方案。 在结构冒险和数据冒险中,你会发现,所有的流水线停顿操作都要从 指令执行阶 段开始。流水线的前两个阶段,也就是取指令(IF)和指令译码(ID)的阶段,是不需要停顿的。CPU 会在流水线里面直接去取下一条指令,然后进行译码。 2、一旦遇到 if…else 这样的条件分支,或者 for/while 循环就会不成立 取指令和指令译码不会需要遇到任何停顿,这是基于一个假设。这个假设就是,所有的指令代码都是顺序加载执行的。不过这个假设,在执行的代码中,一旦遇到 if…else 这样的条件分支, 或者 for/while 循环,就会不成立。 我们先来回顾一下,第6讲里讲的cmp比较指令、jmp和jle这样的条件跳转指令。可以看到,在jmp指令发生的时候,CPU可能会跳转去执行其他指令。jmp后的那一条指令是否应该顺序加载执行, 在流水线里面进行取指令的时候,我们没法知道。要等jmp指令执行完成,去更新了PC寄存器之后,我们才能知道,是否执行下一条指令,还是跳转到另外一个内存地址,去取别的指令 3、如何解决停顿 这种为了确保能取到正确的指令,而不得不进行等待延迟的情况,就是今天我们要讲的 控制冒险

深入浅出计算机组成原理:冒险和预测(三):CPU里的“线程池”(第24讲)

北战南征 提交于 2019-11-29 00:38:24
一 、引子 过去两讲,我为你讲解了通过增加资源、停顿等待以及主动转发数据的方式,来解决结构冒险和数据冒险问题。对于结构冒险,由于限制来自于同一时钟周期不同的指令, 要访问相同的硬件资源,解决方案是增加资源。对于数据冒险,由于限制来自于数据之间的各种依赖,我们可以提前把数据转发到下一个指令。 但是即便综合运用这三种技术,我们仍然会遇到不得不停下整个流水线,等待前面的指令完成的情况,也就是采用流水线停顿的解决方案。比如说,上一讲里最后给你的例子, 即使我们进行了操作数前推,因为第二条条加法指令依赖于第一条指令从内存中获取的数据,我们还是要插入一次NOP的操作。 那我们能不能让后面没有数据依赖的指令,在前面指令停顿的时候先执行呢? 答案当然是可以的。毕竟,流水线停顿的时候,对应的电路闲着也是闲着。那我们完全可以先完成后面指令的执行阶段。 二、填上空闲的NOP:上菜的顺序不必是点菜的顺序 之前我为你讲解的,无论是流水线停顿,还是操作数前推,归根到底,只要前面指令的特定阶段还没有执行完成,后面的指令就会被“阻塞”住。 但是这个“阻塞”很多时候是没有必要的。因为尽管你的代码生成的指令是顺序的,但是如果后面的指令不需要依赖前面指令的执行结果,完全可以不必等待前面的指令运算完成。 比如说,下面这三行代码。 计算里面的 x ,却要等待 a 和 d 都计算完成,实在没啥必要。所以我们完全可以在 d

深入浅出计算机组成原理:GPU(下)-为什么深度学习需要使用GPU?(第31讲)

柔情痞子 提交于 2019-11-28 17:47:39
一、引子 上一讲,我带你一起看了三维图形在计算机里的渲染过程。这个渲染过程,分成了顶点处理、图元处理、栅格化、片段处理,以及最后的像素操作。这一连串的过程, 也被称之为图形流水线或者渲染管线。 因为要实时计算渲染的像素特别地多,图形加速卡登上了历史的舞台。通过3dFx的Voodoo或者NVidia的TNT这样的图形加速卡, CPU就不需要再去处理一个个像素点的图元处理、栅格化和片段处理这些操作。而3D游戏也是从这个时代发展起来的。 你可以看这张图,这是“古墓丽影”游戏的多边形建模的变化。这个变化,则是从1996年到2016年,这20年来显卡的进步带来的。 二、Shader的诞生和可编程图形处理器 1、无论你的显卡有多快,如果CPU不行,3D画面一样还是不行 不知道你有没有发现,在Voodoo和TNT显卡的渲染管线里面,没有“顶点处理“这个步骤。在当时,把多边形的顶点进行线性变化,转化到我们的屏幕的坐标系的工作还是由CPU完成的。 所以,CPU的性能越好,能够支持的多边形也就越多,对应的多边形建模的效果自然也就越像真人。而3D游戏的多边形性能也受限 于我们CPU的性能。无论你的显卡有多快,如果CPU不行,3D画面一样还是不行。 2、1999年NVidia推出的GeForce 256显卡 所以,1999年NVidia推出的GeForce 256显卡,就把顶点处理的计算能力

漫谈计算机组成原理(九)定点数及定点数的运算

痴心易碎 提交于 2019-11-28 16:02:30
本文讲什么? 在计算机中,小数点并没有用专门的器件去表示,而是按照一种约定的方式,统一存储在寄存器单元中的。算数逻辑运算单元(ALU)是CPU的组成部分,负责算数和逻辑的运算。那么,ALU究竟是如何工作的呢? 这就是本文主要探讨的内容: 什么是定点数? 定点数的位移、加、减、乘、除运算是如何进行的? 定点数是啥? 从字面意思来理解,“定点数”就是“点”不动的数。那么究竟是什么“点”不动呢?没错,就是“小数点”。 在上一讲我们说道,不论是整数还是小数,都是有小数点的。 整数的小数点表示在最后一位数字的后面,而小数的小数点标识在真值的符号位后面。 如图所示: 除了定点数,还有一种数叫做“浮点数”,浮点数将在下一讲展开介绍。 定点数的运算 好了,介绍完定点数的基本概念以后,我们展开讲定点数的位移运算和四则运算。定点数的四则运算实际上要比我们想象的复杂的多。 机器并不像人,一眼就知道二二得四,他需要知道2的定点表示形式,然后两个定点数相乘,相乘是有一定的过程的,经过了这个过程,才能得到结果的二进制数,最终输出给我们。 我们要做的,就是了解加减乘除究竟经历了什么样子的过程 。 定点数的位移运算 不要看移位运算简单,但是它在计算机的运算中的地位是举足轻重的。没有移位运算,也就没有后面的乘除法,乘除法就是在移位运算和加减运算的配合下实现的。 移位运算的规则: 虽然正数和负数的移位运算规则不相同

深入浅出计算机组成原理学习笔记:DMA:为什么Kafka这么快?(第48讲)

时光总嘲笑我的痴心妄想 提交于 2019-11-28 15:52:48
一、引子 过去几年里,整个计算机产业届,都在尝试不停地提升I/O设备的速度。把HDD硬盘换成SSD硬盘,我们仍然觉得不够快;用PCI Express接口的SSD硬盘替代SATA接口的SSD硬盘, 我们还是觉得不够快,所以,现在就有了傲腾(Optane)这样的技术。 但是,无论I/O速度如何提升,比起CPU,总还是太慢。SSD硬盘的IOPS可以到2万、4万,但是我们CPU的主频有2GHz以上,也就意味着每秒会有20亿次的操作。 如果我们对于I/O的操作,都是由CPU发出对应的指令,然后等待I/O设备完成操作之后返回,那CPU有大量的时间其实都是在等待I/O设备完成操作。 但是,这个CPU的等待,在很多时候,其实并没有太多的实际意义。我们对于I/O设备的⼤量操作,其实都只是把内存里面的数据,传输到I/O设备而已。 在这种情况下,其实CPU只是在傻等而已。特别是当传输的 因此,计算机工程师们,就发明了DMA技术,也就是 直接内存访问(Direct Memory Access)技术,来减少CPU等待的时间。 二 、理解DMA,一个协处理器 1、什么是DMA? 其实DMA技术很容易理解,本质上,DMA技术就是我们在主板上放⼀块独立的芯片。在进行内存和I/O设备的数据传输的时候,我们不再通过CPU来控制数据传输, 而直接通过 DMA控制器(DMA?Controller,简称DMAC)。这块芯片

深入浅出计算机组成原理学习笔记:SSD硬盘(下)-如何完成性能优化的KPI?(第47讲)

て烟熏妆下的殇ゞ 提交于 2019-11-28 15:52:44
一、引子 1、为什么Windows操作系统、用了SSD的系统盘,就不能用磁盘碎篇整理功能? 如果你平时用的是Windows电脑,你会发现,用了SSD的系统盘,就不能用磁盘碎片整理功能。这是因为,一旦主动去运行磁盘碎片整理功能,就会发生一次块的擦除, 对应块的寿命就少了一点点。这个SSD的擦除寿命的问题,不仅会影响像磁盘碎片整理这样的功能,其实也很影响我们的日常使用。 2、读多的场景 我们的操作系统上,并没有SSD硬盘上各个块纸目前已经擦写的情况和寿命,所以它对待SSD硬盘和普通的机械硬盘没有什么区别。 我们日常使用PC进行软件开发的时候,会先在硬盘上装上操作系统和常用软件,比如Office,或者工程师们会装上VS Code、WebStorm这样的集成开发环境。 这些软件所在的块,写入一次之后,就不太会擦除了,所以就只有读的需求。 3、写多的场景 一旦开始开发,我们就会不断添加新的代码文件,还会不断修改已经有的代码文件。因为SSD硬盘没有覆写(Override)的功能,所以,这个过程中,其实我们是在反复地写入新的文件,然后再把原来的文件标记成逻辑上删除的状态。等SSD里面空的块少了, 我们会用“垃圾回收”的方式,进行擦除。这样,我们的擦除会反复发现在这些用来存放数据的地方。 有一天,这些块的擦除次数到了,变成了坏块。但是,我们安装操作系统和软件的地方还没有坏