计算机组成原理

计算机的基本硬件组成

  1. 三大基本部分:CPU、内存、主板
  2. 芯片组和总线实现CPU和内存之间的通信
  3. 显卡里有GPU
  4. 南桥芯片组实现CPU和IO设备的通信
  5. 冯·诺依曼体系结构,即存储程序计算机,最初设计的报告被特称为First Draft,需要处理器单元(计算)、控制器单元(流程)、内存、输入输出

计算机性能

  1. 响应时间、吞吐率
  2. 计算机的计时单位:CPU时钟
  3. 程序实际花费的 CPU 执行时间(CPU Time),就是 user time加sys time
  4. 程序的 CPU 执行时间 =CPU 时钟周期数×时钟周期时间
  5. CPU 时钟周期数,我们可以再做一个分解,把它变成“指令数×每条指令的平均时钟周期数(CPI)
提升性能
  1. 摩尔定律与并行优化
  2. CPU功耗 ~= 1/2 ×负载电容×电压的平方×开关频率×晶体管数量,由于功耗带来的散热问题,限制了CPU晶体管数量和主频的增长
  3. 多核的并行优化,受阿姆达尔定律限制,
  4. 其余的性能提升方法:加速大概率事件、通过流水线提高性能、通过预测提高性能

计算机指令

常见的机器指令可分为:算术类指令、数据传输类指令、逻辑类指令、条件分支类指令、无条件跳转指令

CPU执行指令
  1. CPU由寄存器组成,寄存器由多个触发器或者锁存器组成
  2. N个触发器或者锁存器,就组成N bit的寄存器
  3. 三种特殊寄存器:PC寄存器、指令寄存器、条件码寄存器
  4. 硬件层面实现if和for循环,只需要以上三种特殊寄存器
栈溢出
  1. 函数的跳转比起if和for循环的跳转,需要记录返回的地址,这就是压栈与出栈
  2. 整个函数 A 所占用的所有内存空间,就是函数 A 的栈帧(Stack Frame)
  3. 一层层压栈之后,栈顶的内存地址是在逐渐变小而不是变大
  4. rbp 又叫栈帧指针(Frame Pointer),是一个存放了当前栈帧位置的寄存器,rsp
  5. 函数内联:当没有嵌套调用时,将产生的函数指令插入到调用的位置进行优化
  6. 函数作用域内的临时变量,分配在栈上
  7. 把大的for循环写里面能提高CPU流水线的分支预测的准确率
编译、链接和装载
  1. 只有通过链接器(Linker)把多个目标文件(obj)以及调用的各种函数库链接起来,我们才能得到一个可执行文件
  2. 可执行文件和目标文件所使用的都是一种叫ELF格式,即可执行与可链接文件格式
  3. ELF 文件里面,存储在一个叫作符号表(Symbols Table)的位置。符号表相当于一个地址簿,把名字和地址关联了起来。
  4. Windows 的可执行文件格式是一种叫作PE(Portable Executable Format)的文件格式,所以在linux下执行的程序不能在windows下执行
  5. 可执行程序加载后占用的内存空间应该是连续的,我们需要同时加载很多个程序,并且不能让程序自己规定在内存中加载的位置
  6. 指令里用到的内存地址叫作虚拟内存地址(Virtual Memory Address),实际在内存硬件里面的空间地址,我们叫物理内存地址(Physical Memory Address)
  7. 这种找出一段连续的物理内存和虚拟内存地址进行映射的方法,我们叫分段(Segmentation),分段造成了内存碎片问题,通过内存交换解决
  8. 内存分页是把整个物理内存空间切成一段段固定尺寸的大小
  9. 动态链接,共享库windows下为dll,linux下为so
  10. 在共享库的 data section 里面,保存了一张全局偏移表(GOT,Global Offset Table)。虽然共享库的代码部分的物理内存是共享的,但是数据部分是各个动态链接它的应用程序里面各加载一份的
编码
  1. 我们仍然通过最左侧第一位的 0 和 1,来判断这个数的正负。但是,我们不再把这一位当成单独的符号位,在剩下几位计算出的十进制前加上正负号,而是在计算整个二进制值的时候,在左侧最高位前面加个负号
  2. 不管是整数也好,浮点数也好,采用二进制序列化会比存储文本省下不少空间
  3. ASCII、Unicode是字符集,UTF-8是字符编码
电路
  1. 通过一个异或门计算出个位,通过一个与门计算出是否进位,打包称为半加器
  2. 两个半加器和一个或门,组成全加器
  3. 门延迟与时钟频率
浮点数
  1. BCD编码:定点数
  2. 32bit浮点数组成:1bit符号位+8bit指数位+23比特有效数位,表示为科学计数法
  3. 浮点数先对齐再计算,所以对应指数位较小的数在计算之前有效位会右移,所以最右侧有效位精度丢失
  4. Kahan summation解决精度丢失

处理器

指令+运算=CPU
  1. fetch-decode-execute 指令周期
  2. 从内存里面读取一条指令的最短时间,称为 CPU 周期或机器周期
  3. 数据通路就是我们的处理器单元,它通常由操作元件即组合逻辑元件ALU和存储元件构成。数据通路加上控制器组成CPU
  4. CPU需要的 4 种基本电路。它们分别是,ALU 这样的组合逻辑电路、用来存储数据的锁存器和 D 触发器电路、用来实现 PC 寄存器的计数器电路,以及用来解码和寻址的译码器电路
  5. 组合逻辑电路、时序逻辑电路
  6. 时钟信号:反馈电路,即反相器,
  7. 触发器:当两个开关都断开的时候,最终的输出结果,取决于之前动作的输出,具有记忆性
  8. 可以由时钟信号、加法器、D型触发器构成自增的PC寄存器
指令流水线
  1. 不用把时钟周期设置成整条指令执行的时间,而是拆分成完成这样的一个一个小步骤需要的时间,这样的协作模式,就是我们所说的指令流水线。这里面每一个独立的步骤,我们就称之为流水线阶段或者流水线级(Pipeline Stage)
  2. 流水线技术并不能缩短单条指令的响应时间这个性能指标,但是可以增加在运行很多条指令时候的吞吐率
  3. 流水线设计的三大冒险:结构冒险、数据冒险、控制冒险
  4. 结构冒险:借鉴了哈佛结构的思路,虽然没有把内存分开,但是把高速缓存分成了指令缓存和数据缓存两部分
  5. 数据冒险:先写后读存在数据依赖的风险,先读后写即反依赖,写后再写即输出依赖,最简单是通过流水线冒泡等待解决
  6. 解决冒险的方法:操作数前推(转发),硬件上为旁路;乱序执行;缩短分支延迟、静态分支预测(失败则flush或zap)、动态分支预测(1比特饱和计数、状态机即2比特饱和计数)
  7. 多层嵌套循环时把大循环写在内部,减少分支预测失败带来的开销(是最后一层循环的临时变量创建次数,属于栈的问题?)
  8. 通过更改硬件设计,一次取出多条指令,并行指令译码,叫做多发射和超标量
加速矩阵乘法
  1. 超线程:通过硬件设计实现逻辑上的多CPU,并行运行程序,也称作同时多线程
  2. 单指令多数据流,一种数据并行的方案,一次取出多条数据,刚好适合向量不同维度的独立计算
异常处理
  1. 检测异常,拿到异常码,再根据异常码进行查表处理
  2. 中断(来源I/O设备)、陷阱(断点,最常见的是应用程序调用系统调用即用户态切换到内核态时)、故障、中止
  3. 对于异常这样的处理流程,不像是顺序执行的指令间的函数调用关系。而是更像两个不同的独立进程之间在 CPU 层面的切换,所以这个过程我们称之为上下文切换
处理器综合
  1. CISC提出了微指令架构,向RISC靠近
  2. 三维图形在计算机里的渲染过程。这个渲染过程,分成了顶点处理、图元处理、 栅格化、片段处理,以及最后的像素操作
  3. GPU: 统一着色器架构 把任务交给shader或者cuba
  4. 从一个 CPU 的硬件电路出发,去掉了对 GPU 没有什么用的分支预测和乱序执行电路,来进行瘦身。之后,基于渲染管线里面顶点处理和片段处理就是天然可以并行的了。在 GPU 里面可以加上很多个核。
  5. 渲染管线里面,整个指令流程是相同的,所以又引入了和 CPU 里的 SIMD 类似的 SIMT 架构。这个改动,进一步增加了 GPU 里面的 ALU 的数量。最后,为了能够让 GPU 不要遭遇流水线停顿,又在同一个 GPU 的计算核里面,加上了更多的执行上下文,让 GPU 始终保持繁忙
  6. FPGA:现场可编程门阵列,用存储换功能实现组合逻辑(有一张LUT表)、对于需要实现的时序逻辑电路,我们可以在 FPGA 里面直接放上 D 触发器,作为寄存器,FPGA 是通过可编程逻辑布线,来连接各个不同的 CLB,最终实现我们想要实现的芯片功能
  7. ASIC: 专用集成电路
  8. 虚拟机:解释型虚拟机、虚拟机监视器(type2与解释型并无太大区别,type1直接调用硬件,系统级的硬件)、docker

计算机存储与IO

  1. CPU的寄存器、CPU cache(SRAM,分成L1、L2、L3三层)、内存(DRAM)、硬盘
  2. 时间局部性原理:LRU算法
  3. CPU高速缓存:弥补CPU和内存之间的性能差异,数据单元为cache line即缓存块;直接映射:通过求余的方法将内存中的block地址与cache line地址形成映射;组标记:根据低位确认cache line地址后,根据组标记即记录的高位确认是否是该数据
  4. 一个内存从CPU高速缓存中的访问地址,最终包括高位代表的组标记、低位代表的索引,以及在对应的 Data Block 中定位对应字的位置偏移量。
  5. 不同线程变量共享时注意缓存一致性的问题;写入方法有写直达、写回
  6. 多核CPU保持高速缓存一致性:总线嗅探,写失效、写广播、MESI协议
  7. 在程序运行的时候,内存地址从顶部往下,不断分配占用的栈的空间。而堆的空间,内存地址则是从底部往上,是不断分配占用的
  8. 解决虚拟地址与物理地址映射表过大的问题:多级页表就像一个多叉树的数据结构,所以我们常常称它为页表树
  9. 加速地址转换:TLB,专门在 CPU 里放了一块缓存芯片,全称是地址变换高速缓冲,在 CPU 芯片里面,我们封装了内存管理单元(MMU,Memory Management Unit)芯片,用来完成地址转换。和 TLB 的访问和交互,都是由这个 MMU 控制的。
  10. 内存保护:地址空间布局随机化
  11. 双独立总线(Dual Independent Bus,缩写为 DIB)。CPU 里,有一个快速的本地总线(Local Bus),连接高速缓存,以及一个速度相对较慢的前端总线(Front-side Bus)向外连接,从物理上可以分为数据线、地址线、控制线,
  12. 北桥芯片连接CPU、内存
  13. 输入输出设备,由接口和实际的I/O设备组成,获得命令
  14. CPU和IO设备通信:内存映射IO
  15. 硬盘IO指标:IOPS(每秒输入输出操作数)、DTR(数据传输率)
  16. 硬盘提升IOPS:partial stroking,牺牲部分磁道的存储空间,换取时间
  17. SSD:适合用于读多写少的业务情景
  18. 解决SSD擦除的磨损问题:增加了FTL(闪存转换层)的磨损均衡,SSD需要垃圾回收,导致了写入放大,带来了性能问题
  19. 解除IO与CPU耦合:DMA,即直接内存访问,DMAC 最有价值的地方体现在,当我们要传输的数据特别大、速度特别快,或者传输的数据特别小、速度特别慢的时候。kafka利用DMA,把数据直接搬运到操作系统内核读缓存区,再从读缓存区发送到网卡缓存区,把四次搬运优化到两次,没有在内存层面拷贝,被称作零拷贝
  20. 异地多活的系统设计
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值