21天打卡行动#
课程:《深入浅出计算机组成原理》
笔记#11:
SISD 单指令单数据(Single Instruction Single Data)
SIMD 单指令多数据(Single Instruction Multiple Data)
MIMD 多指令多数据(Multiple Instruction Multiple Data)
无论多个CPU核心运行不同的程序,还是在单个CPU核心里面切换运行不同县城的任务,
在同一时间点上,一个物理CPU核心只会运行一个线程的指令。
超线程是通过增加物理电路使一个CPU核心内部可以维护两个不同线程指令的状态信息。
超线程也被叫做同时多线程。
并行计算方案:超线程和SIMD
通过一个物理CPU核心“装作”两个逻辑岑面的CPU核心,使得CPU可以同时运行两个不同县城的指令。
处理向量不同维度之间的计算时它们是相互独立的。CPU的寄存器放得下多条数据,这时可以一次取出多条数据,交给CPU进行并行计算。
21天打卡行动#
课程:《深入浅出计算机组成原理》
笔记#12:
异常和中断
异常:异常的前半部分即异常的发生和捕捉,在硬件层面完成;异常的后半部分即异常的处理,由软件来完成。
CPU中断向量表:CPU获取异常码之后,将当前程序的执行线程,保存到程序栈里,查询异常码,处理异常,异常处理完之后,继续执行之前程序。
异常分为:
中断:程序运行一般,被打断。来自CPU外部的I/O设备,比如:键盘或鼠标操作。
陷阱:陷阱(Trap)。在程序种打断点,程序运行到这个位置就会跳进陷阱。
故障:陷阱为故意触发,故障不在计划内,需要异常处理程序取处理。
中止:CPU遇到异常无法恢复时不得不中止。
异常发生之后,需要进行一次上下文切换。
21天打卡行动#
课程:《深入浅出计算机组成原理》
笔记#13:
手机芯片为什么都是ARM?
复杂指令集(Complex Instruction Set Computing CISC):CPU指令集机器码不是固定长度。
简单指令集(Reduced Instruction Set Compution RISC):CPU指令集机器码是固定长度。
在RISC中,只保留了最常用的20%的简单指令,另外80%的复杂指令通过简单指令组合起来实现。
这样做的好处是RISC电路设计变简单了,提高性能也更容易了。
程序的CPU执行时间=指令数×CPI×Clock Cycle Time
CISC通过优化指令数,减少CPU执行时间。
RISC通过优化CPI,减少CPU执行时间。
ARM正真能够战胜Intel,主要由以下几点:
1)功耗设计。一个4核Intel i7 CPU工具130W,而ARM A8单核CPU只有2W功耗;
2)低价。ARM只设计CPU,不制造CPU。苹果、三星、华为都拿到了基本时长上。
ARM不是开源的。
21天打卡行动#
课程:《深入浅出计算机组成原理》
笔记#14:
玩游戏为什么需要GPU?
图形流水线
我们电脑里面显示出来的3D画面,都时通过多边形组合出来的而不是通过相机或者摄像头拍出来的。
对于图像进行实时渲染的过程,可以分解成下面5个步骤:
- 顶点处理(Vertex Processing):三维顶点二维化
- 图元处理(Primitive Processing):对不再屏幕种的图元进行剔除和裁剪
- 栅格处化(Rasterization):二维坐标像素化
- 片段处理(Fragment Processing):计算每个像素的颜色、透明度
- 像素操作(Pixel Operations):把不同多边形的像素混合到一起
以上五个步骤的渲染过程,我们称之为图形流水线(Graphic Pipeline)。
图形渲染计算量预估
1、以屏幕分辨率640*480进行计算,屏幕上大概有30万个像素点
2、为了让屏幕不闪烁,我们假设屏幕刷新为60帧,即每秒刷新60次,即1800万次单个像素渲染
3、从栅格化开始有三个流水线步骤,我们需要5400万条指令,即54M指令
4、90年代的CPU主频大概都在60MHz~100MHz之内,54M基本把CPU用完了。
没有GPU,根本无法支持3D图形显示。
21天打卡行动#
课程:《深入浅出计算机组成原理》
笔记#15:
深度学习为什么需要GPU?
早期的GPU主要用于图形计算,不可对GPU编程。
2001年从Direct3D 8.0开始,微软第一次引入了可编程管线。一开始可编程管线仅限于顶点处理、片段处理部分。
这些可编程的接口称之为Shader,中文名是着色器,之所以叫着色器,是因为一开始这些接口主要用来处理光照、亮度、颜色等。
一开始Sharder 分为 Vertex Shader和Fragment Shader。因为顶点处理与片段处理时顺序执行的所以同一时间一定有一半Shader是空闲的;
所以后来提出了统一着色器架构(Unified Shader Architecture)——在GPU里放多个一样的Shader硬件电路,通过统一调度,把顶点处理、
图元处理、片段处理都交给Shader处理。让整个GPU尽量忙起来,这就是现代GPU的设计。
Shader编程了一个通用模块,就有了把GPU拿来做各种通用计算用法,即GPGPU(General-Purpose Computing On Graphice Processing Units)
通用图形处理器。
21天打卡行动#
课程:《深入浅出计算机组成原理》
笔记#16:
现代GPU的三个核心创意
为什么现代GPU在图形渲染、深度学习上会那么快?
1、芯片瘦身
GPU基于CPU改造而来,将不需要的电路都去掉,只留下取指令、指令译码、ALU及执行指令需要的寄存器和缓存。
2、多核并行和SIMT
GPU电路简化之后,我们可以在GPU种加入多个GPU电路,就如同多核CPU一样。
和CPU不同,GPU运算天然就是并行的,我们不需要单独实现多线程计算。
GPU借鉴了CPU种SIMD,用了一种叫做SIMT(Single Instruction, Multiple Threads)的技术。
CPU种SIMD一次性去除了固定长度的多个数据放到寄存器中,用一个指令取执行,在GPU中SIMT可以把多条数据,交给不同的线程取处理。
各个线程中执行的指令是一样的,但是由于数据不同,可能会走到不同的分支。
相同的代码,相同的流程,可能执行不同的具体指令。
GPU可以进一步改进,取出的指令可以交给多个不同的ALU并行进行运算。在一个GPU核里可以放多个ALU单元。
执行上下文可以分为两部分,每个计算单元都有一个对应的线程上下文,共用的内容可以放到共享上下文中。
21天打卡行动#
课程:《深入浅出计算机组成原理》
笔记#17:
GPU里的“超线程”
GPU主要以数值计算为主,但不可避免会有if..else分支,GPU中没有CPU中对应的分支预测电路,这样GPU也可能会出现流水线停顿。
如同CPU中的超线程一样,遇到流水线停顿的时候可以调度别的计算任务给ALU,任务调度就需要保存执行上下文,便于恢复执行上下文。
针对这个需求,GPU中执行上下文的个数要比计算单元ALU的个数多。
现在的深度学习计算,都是超大的向量和矩阵,海量的训练样本计算。整个计算过程中没有复杂的逻辑和分支,非常适合GPU这样的并行、计算能力强的架构。
Nvidia2080显卡,共有46个SM(Streaming Multiprocessor,流失处理器)即GPU Core,46核GPU。
每个SM里面有64个Cuda Core(相当于ALU或Pixel Shader),46x64一共有2944个Shader,还有184个TMU(Texture Mapping Unit)纹理影射计算单元。
2088的主频是1515MHz,超频后可达1700Mhz,Nvidia显卡,每个时钟周期可以执行2条指令,所以它的浮点数计算能力,是:
(2944+184)x1700Mhzx2 =10.06TFLOPS
Intel i9 9900K性能不到1TFLOPS,与Nvidia2080价格差不多,能力差10倍。
21天打卡行动#
课程:《深入浅出计算机组成原理》
笔记#18:
volatile 这个关键字有什么作用?
两种常见误解:
1.把volatile 当成一种锁机制,认为给变量加上了 volatile,就好像是给函数加了 sychronized 关键字一样,不同的线程对于特定变量的访问会去加锁;
2.把 volatile 当成一种原子化的操作机制,认为加了 volatile 之后,对于一个变量的自增的操作就会变成原子性的了。
正解:
volatile设计的目的是为了,确保我们对于这个变量的读取和写入,都一定会同步到主内存里,而不是从 Cache 里面读取。
21天打卡行动#
课程:《深入浅出计算机组成原理》
笔记#19:
CPU 高速缓存的写入
1、写入 Cache 的性能也比写入主内存要快,那我们写入的数据,到底应该写到 Cache 里还是主内存呢?如果我们直接写入到主内存里,Cache 里的数据是否会失效呢?
两种策略
写直达(Write-Through)
写入前,先判断是否在Cache中,如果在先更新Cache内容再写入主存,否则直接,写入主存。
写回(Write-Back)
因为我们每次读数据,都从Cache中读,我们可以只更新Cache中的数据,只有Cache中的数据被替换时才将数据同步到主存。
2、多个 CPU 核的缓存一致性的问题。
引入MESI 协议
21天打卡行动#
课程:《深入浅出计算机组成原理》
笔记#20:
缓存一致性
想要实现缓存一致性,关键是要满足两点。
1、写传播,也就是在一个 CPU 核心写入的内容,需要传播到其他 CPU 核心里。
2、保障事务的串行化,才能保障我们的数据是真正一致的,我们的程序在各个不同的核心上运行的结果也是一致的。
多个不同的链接去访问数据库,我们必须做到事务的串行,否则很难做到保证数据的可靠性。
需要做到两点才可以保证事务串行
1、一个 CPU 核心对于数据的操作,需要同步通信给到其他 CPU 核心;
2、两个 CPU 核心里有同一个数据的 Cache,那么对于这个 Cache 数据的更新,需要有一个“锁”的概念。
21天打卡行动#
课程:《深入浅出计算机组成原理》
笔记#21:
MESI 协议的由来呢,来自于我们对 Cache Line 的四个不同的标记,分别是:
M:代表已修改(Modified)
对应Cache中标记为脏的数据
E:代表独占(Exclusive)
表示这个数据只在当前Cache,可以随意修改
S:代表共享(Shared)
表示数据在多个Cache,修改需要通知其他Cache
I:代表已失效(Invalidated)
表示数据已失效
MESI 协议有限状态机