1
1
mirror of https://github.com/foxsen/archbase.git synced 2026-02-03 02:14:40 +08:00
Files
archbase/15-organization.Rmd
Zhang Fuxin 6f18f75d58 修改错别字:续写=》读写
感谢@baiyunkai12指出问题

Resolved #23
2021-11-29 13:35:14 +08:00

413 lines
62 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# (PART) 计算机硬件结构 {-}
# 计算机组成原理和结构
前面章节介绍的计算机指令系统结构从软件的角度描述了计算机功能,从本章开始将介绍计算机组成结构,从硬件的角度来看看计算机是怎样构成的。
如果说图灵机是现代计算机的计算理论模型,冯·诺依曼结构就是现代计算机的结构理论模型。本章从冯·诺依曼的理论模型开始,介绍计算机系统的各个组成部分,并与现代计算机的具体实现相对应。
## 冯·诺依曼结构
现代计算机都采用存储程序结构又称为冯·诺依曼结构是1945年匈牙利籍数学家冯·诺依曼受宾夕法尼亚大学研制的ENIAC计算机结构的启发提出的是世界上第一个完整的计算机体系结构。
冯·诺依曼结构的主要特点是①计算机由存储器、运算器、控制器、输入设备和输出设备五部分组成其中运算器和控制器合称为中央处理器Central Processing Processor简称CPU。②存储器是按地址访问的线性编址的一维结构每个单元的位数固定。③采用存储程序方式即指令和数据不加区别混合存储在同一个存储器中。④控制器通过执行指令发出控制信号控制计算机的操作。指令在存储器中按其执行顺序存放由指令计数器指明要执行的指令所在的单元地址。指令计数器一般按顺序递增但执行顺序可按运算结果或当时的外界条件而改变。⑤以运算器为中心输入输出设备与存储器之间的数据传送都经过运算器。冯·诺依曼计算机的工作原理如图\@ref(fig:von-architecture)所示。
```{r von-architecture, echo=FALSE, fig.align='center', fig.cap="冯·诺依曼计算机体系结构", out.width='50%'}
knitr::include_graphics("images/chapter5/von_architecture.png")
```
随着技术的进步冯·诺依曼结构得到了持续的改进主要包括以下几个方面①由以运算器为中心改进为以存储器为中心。使数据的流向更加合理从而使运算器、存储器和输入输出设备能够并行工作。②由单一的集中控制改进为分散控制。计算机发展初期工作速度很低运算器、存储器、控制器和输入输出设备可以在同一个时钟信号的控制下同步工作。现在运算器、内存与输入输出设备的速度差异很大需要采用异步方式分散控制。③从基于串行算法改进为适应并行算法。出现了流水线处理器、超标量处理器、向量处理器、多核处理器、对称多处理器Symmetric Multiprocessor简称SMP、大规模并行处理机Massively Parallel Processing简称MPP和机群系统等。④出现为适应特殊需要的专用计算机如图形处理器Graphic Processing Unit简称GPU、数字信号处理器Digital Signal Processor简称DSP等。⑤在非冯·诺依曼计算机的研究方面也取得一些成果如依靠数据驱动的数据流计算机、图归约计算机等。
虽然经过了长期的发展,现代计算机系统占据主要地位的仍然是以存储程序和指令驱动执行为主要特点的冯·诺依曼结构。
作为冯·诺依曼结构的一个变种,哈佛结构把程序和数据分开存储。控制器使用两条独立的总线读取程序和访问数据,程序空间和数据空间完成分开。在通用计算机领域,由于应用软件的多样性,要求计算机不断地变化所执行的程序内容,并且频繁地对数据与程序占用的存储器资源进行重新分配,使用统一编址可以最大限度地利用资源。但是在嵌入式应用中,系统要执行的任务相对单一,程序一般是固化在硬件里的,同时嵌入式系统对安全性、可靠性的要求更高,哈佛结构独立的程序空间更有利于代码保护。因此,在嵌入式领域,哈佛结构得到了广泛应用。需要指出的是,哈佛结构并没有改变冯·诺依曼结构存储程序和指令驱动执行的本质,它只是冯·诺依曼结构的一个变种,并不是独立于冯·诺依曼结构的一种新型结构。
## 计算机的组成部件
本节对计算机的主要组成部件进行介绍。按照冯·诺依曼结构,计算机包含五大部分,即运算器、控制器、存储器、输入设备和输出设备。
### 运算器
运算器是计算机中负责计算包括算术计算和逻辑计算等的部件。运算器包括算术和逻辑运算部件Arithmetic Logic Units简称ALU、移位部件、浮点运算部件Floating Point Units简称FPU、向量运算部件、寄存器等。其中复杂运算如乘除法、开方及浮点运算可用程序实现或由运算器实现。寄存器既可用于保存数据也可用于保存地址。运算器还可设置条件码寄存器等专用寄存器条件码寄存器保存当前运算结果的状态如运算结果是正数、负数或零是否溢出等。
运算器支持的运算类型经历了从简单到复杂的过程。最初的运算器只有简单的定点加减和基本逻辑运算复杂运算如乘除通过加减、移位指令构成的数学库完成后来逐渐出现硬件定点乘法器和除法器。在早期的微处理器中浮点运算器以协处理器的形式出现在计算机中如Intel 8087协处理器包含二进制浮点数的加、减、乘、除等运算现代的通用微处理器则普遍包含完整的浮点运算部件。20世纪90年代开始微处理器中出现了单指令多数据Single Instruction Multiple Data简称SIMD的向量运算器部分处理器还实现了超越函数硬件运算单元如sin、cos、exp、log等。部分用于银行业务处理的计算机如IBM Power系列还实现了十进制定、浮点数的运算器。
随着晶体管集成度的不断提升处理器中所集成的运算器的数量也持续增加通常将具有相近属性的一类运算组织在一起构成一个运算单元。不同的处理器有不同的运算单元组织有的倾向于每个单元大而全有的倾向于每个单元的功能相对单一。处理器中包含的运算单元数目也逐渐增加从早期的单个运算单元逐渐增加到多个运算单元。由于运算单元都需要从寄存器中读取操作数并把结果写回寄存器因此处理器中运算单元的个数主要受限于寄存器堆读写端口个数。运算单元一般按照定点、浮点、访存、向量等大类来组织也有混合的如SIMD部件既能做定点也能做浮点运算定点部件也可以做访存地址计算等。
表\@ref(tab:alu)给出了几种经典处理器的运算器结构。其中Alpha 21264、MIPS R10000、HP PA8700、Ultra Sparc III、Power 4是20世纪90年代RISC处理器鼎盛时期经典的微处理器而Intel Skylake、AMD Zen、Power 8、龙芯3A5000则是最新处理器。
```{r alu, echo = FALSE, message=FALSE, tab.cap='经典处理器的运算器结构'}
autonum <- run_autonum(seq_id = "tab", bkm = "alu", bkm_all = TRUE)
readr::read_csv('./materials/chapter5/alu.csv') %>%
flextable() %>%
set_caption(caption="经典处理器的运算器结构", autonum = autonum) %>%
width(j=1, width=1.3) %>%
width(j=2, width=2.0) %>%
width(j=3, width=2.6) %>%
theme_box()
```
### 控制器
控制器是计算机中发出控制命令以控制计算机各部件自动、协调地工作的装置。控制器控制指令流和每条指令的执行内含程序计数器和指令寄存器等。程序计数器存放当前执行指令的地址指令寄存器存放当前正在执行的指令。指令通过译码产生控制信号用于控制运算器、存储器、IO设备的工作以及后续指令的获取。这些控制信号可以用硬连线逻辑产生也可以用微程序产生也可以两者结合产生。为了获得高指令吞吐率可以采用指令重叠执行的流水线技术以及同时执行多条指令的超标量技术。当遇到执行时间较长或条件不具备的指令时把条件具备的后续指令提前执行称为乱序执行可以提高流水线效率。控制器还产生一定频率的时钟脉冲用于计算机各组成部分的同步。
由于控制器和运算器的紧密耦合关系现代计算机通常把控制器和运算器集成在一起称为中央处理器即CPU。随着芯片集成度的不断提高现代CPU除了含有运算器和控制器外常常还集成了其他部件比如高速缓存Cache部件、内存控制器等。
计算机执行指令一般包含以下过程:从存储器取指令并对取回的指令进行译码,从存储器或寄存器读取指令执行需要的操作数,执行指令,把执行结果写回存储器或寄存器。上述过程称为一个指令周期。计算机不断重复指令周期直到完成程序的执行。体系结构研究的一个永恒主题就是不断加速上述指令执行周期,从而提高计算机运行程序的效率。由于控制器负责控制指令流和每条指令的执行,对提高指令执行效率起着至关重要的作用。
现代处理器的控制器都通过指令流水线技术来提高指令执行效率。指令流水线把一条指令的执行划分为若干阶段(如分为取指、译码、执行、访存、写回阶段)来减少每个时钟周期的工作量,从而提高主频;并允许多条指令的不同阶段重叠执行实现并行处理(如一条指令处于执行阶段时,另一条指令处于译码阶段)。虽然同一条指令的执行时间没有变短,但处理器在单位时间内执行的指令数增加了。
计算机中的取指部件、运算部件、访存部件都在流水线的调度下具体执行指令规定的操作。运算部件的个数和延迟,访存部件的存储层次、容量和带宽,以及取指部件的转移猜测算法等是决定微结构性能的重要因素。常见的提高流水线效率的技术包括转移预测技术、乱序执行技术、超标量(又称为多发射)技术等。
1转移预测技术。冯·诺依曼结构指令驱动执行的特点使转移指令成为提高流水线效率的瓶颈。典型应用程序平均每5-10条指令中就有一条转移指令而转移指令的后续指令需要等待转移指令执行结果确定后才能取指导致转移指令和后续指令之间不能重叠执行降低了流水线效率。随着主频的提高现代处理器流水线普遍在10-20级之间由于转移指令引起的流水线阻塞成为提高指令流水线效率的重要瓶颈。
转移预测技术可以消除转移指令引起的指令流水线阻塞。转移预测器根据当前转移指令或其他转移指令的历史行为,在转移指令的取指或译码阶段预测该转移指令的跳转方向和目标地址并进行后续指令的取指。转移指令执行后,根据已经确定的跳转方向和目标地址对预测结果进行修正。如果发生转移预测错误,还需要取消指令流水线中的后续指令。为了提高预测精度并降低预测错误时的流水线开销,现代高性能处理器采用了复杂的转移预测器。
例如可以在取指部件中设置一位标志记录上一条转移指令的跳转方向碰到转移指令不用等该转移指令执行结果就根据该标志猜测跳转方向进行取指。对于C语言中的`for (i=0,i<N,i++)`类的循环这种简单的转移猜测就可以达到N-1/N+1的准确度当N很大时准确度很高。
2乱序执行技术。如果指令i是条长延迟指令如除法指令或Cache不命中的访存指令那么在顺序指令流水线中指令i后面的指令需要在流水线中等待很长时间。乱序执行技术通过指令动态调度允许指令i后面的源操作数准备好的指令越过指令i执行需要使用指令i的运算结果的指令由于源操作数没有准备好不会越过指令i执行以提高指令流水线效率。为此在指令译码之后的读寄存器阶段应判断指令需要的操作数是否准备好。如果操作数已经准备好就进入执行阶段如果操作数没有准备好就进入称为保留站或者发射队列的队列中等待直到操作数准备好后再进入执行阶段。为了保证执行结果符合程序规定的要求乱序执行的指令需要有序结束。为此执行完的指令均进入一个称为重排序缓冲Re-Order Buffer简称ROB的队列并把执行结果临时写入重命名寄存器。ROB根据指令进入流水线的次序有序提交指令的执行结果到目标寄存器或存储器。CDC6600和IBM 360/91分别使用记分板和保留站最早实现了指令的动态调度。
就像保留站和重排序缓冲用来临时存储指令以使指令在流水线中流动更加通畅,重命名寄存器用来临时存储数据以使数据在流水线流动更加通畅。保留站、重排序缓冲、重命名寄存器都是微结构中的数据结构,程序员无法用指令来访问,是结构设计人员为了提高流水线效率而用来临时存储指令和数据的。其中,保留站把指令从有序变为无序以提高执行效率,重排序缓存把指令从无序重新变为有序以保证正确性,重命名寄存器则在乱序执行过程中临时存储数据。重命名寄存器与指令可以访问的结构寄存器(如通用寄存器、浮点寄存器)相对应。乱序执行流水线把指令执行结果写入重命名寄存器而不是结构寄存器,以避免破坏结构寄存器的内容,到顺序提交阶段再把重命名寄存器内容写入结构寄存器。两组执行不同运算但使用同一结构寄存器的指令可以使用不同的重命名寄存器,从而避免该结构寄存器成为串行化瓶颈,实现并行执行。
3超标量技术。工艺技术的发展使得在20世纪80年代后期出现了超标量处理器。超标量结构允许指令流水线的每一阶段同时处理多条指令。例如Alpha 21264处理器每拍可以取4条指令发射6条指令写回6条指令提交11条指令。如果把单发射结构比作单车道马路多发射结构就是多车道马路。
由于超标量结构的指令和数据通路都变宽了使得寄存器端口、保留站端口、ROB端口、功能部件数都需要增加例如Alpha 21264的寄存器堆有8个读端口和6个写端口数据Cache的RAM通过倍频支持一拍两次访问。现代超标量处理器一般包含两个以上访存部件两个以上定点运算部件以及两个以上浮点运算部件。超标量结构在指令译码或寄存器重命名时不仅要判断前后拍指令的数据相关还需要判断同一拍中多条指令间的数据相关。
### 存储器
存储器存储程序和数据又称主存储器或内存一般用动态随机访问存储器Dynamic Random Access Memory简称DRAM实现。CPU可以直接访问它IO设备也频繁地与它交换数据。存储器的存取速度往往满足不了CPU的快速要求容量也满足不了应用的需要为此将存储系统分为高速缓存Cache)、主存储器和辅助存储器三个层次。Cache存放当前CPU最频繁访问的部分主存储器内容可以采用比DRAM速度快但容量小的静态随机访问存储器Static Random Access Memory简称SRAM实现。数据和指令在Cache和主存储器之间的调动由硬件自动完成。为扩大存储器容量使用磁盘、磁带、光盘等能存储大量数据的存储器作为辅助存储器。计算机运行时所需的应用程序、系统软件和数据等都先存放在辅助存储器中在运行过程中分批调入主存储器。数据和指令在主存储器和辅助存储器之间的调动由操作系统完成。CPU访问存储器时面对的是一个高速接近于Cache的速度、大容量接近于辅助存储器的容量的存储器。现代计算机中还有少量只读存储器Read Only Memory简称ROM用来存放引导程序和基本输入输出系统Basic Input Output System简称BIOS等。现代计算机访问内存时采用虚拟地址操作系统负责维护虚拟地址和物理地址转换的页表集成在CPU中的存储管理部件Memory Management Unit简称MMU负责把虚拟地址转换为物理地址。
存储器的主要评价指标为存储容量和访问速度。存储容量越大,可以存放的程序和数据越多。访问速度越快,处理器访问的时间越短。对相同容量的存储器,速度越快的存储介质成本越高,而成本越低的存储介质则速度越低。目前人们发明的用于计算机系统的存储介质主要包括以下几类:
1磁性存储介质。如硬盘、磁带等特点是存储密度高、成本低、具有非易失性断电后数据可长期保存缺点是访问速度慢。磁带的访问速度在秒级磁盘的访问速度一般在毫秒级这样的访问速度显然不能满足现代处理器纳秒级周期的速度要求。
2闪存Flash Memory。同样是非易失性的存储介质与磁盘相比它们的访问速度快成本高容量小。随着闪存工艺技术的进步闪存芯片的集成度不断提高成本持续降低闪存正在逐步取代磁盘作为计算机尤其是终端的辅助存储器。
3动态随机访问存储器DRAM。属于易失性存储器断电后数据丢失。特点是存储密度较高存储一位数据只需一个晶体管需要周期性刷新访问速度较快。其访问速度一般在几十纳秒级。
4静态随机访问存储器SRAM。属于易失性存储器断电后数据丢失。存储密度不如DRAM高SRAM存储一位数据需要4-8个晶体管不用周期性刷新但访问速度比DRAM快可以达到纳秒级小容量时能够和处理器核工作在相同的时钟频率。
现代计算机中把上述不同的存储介质组成存储层次,以在成本合适的情况下降低存储访问延迟,如图\@ref(fig:storage-hierarchy)中所示,越往上的层级,速度越快,但成本越高,容量越小;越往下的层级,速度越慢,但成本越低,容量越大。图\@ref(fig:storage-hierarchy)所示存储层次中的寄存器和主存储器直接由指令访问Cache缓存主存储器的部分内容而非易失存储器既是辅助存储器又是输入输出设备非易失存储器的内容由操作系统负责调入调出主存储器。
```{r storage-hierarchy, echo=FALSE, fig.align='center', fig.cap="存储层次", out.width='50%'}
knitr::include_graphics("images/chapter5/storage_hierarchy.png")
```
存储层次的有效性依赖于程序的访存局部性原理包含两个方面一是时间局部性指的是如果一个数据被访问那么在短时间内很有可能被再次访问二是空间局部性指的是如果一个数据被访问那么它的邻近数据也很有可能被访问。利用局部性原理可以把程序近期可能用到的数据存放在靠上的层次把近期内不会用到的数据存放在靠下的层次。通过恰当地控制数据在层次间的移动使处理器需要访问的数据尽可能地出现在靠近处理器的存储层次可以大大提高处理器获得数据的速度从而近似达到用最快的存储器构建一个容量很大的单级存储的效果。现代计算机一般使用多端口寄存器堆实现寄存器使用SRAM来构建片上的高速缓存Cache使用DRAM来构建程序的主存储器也称为主存、内存使用磁盘或闪存来构建大容量的存储器。
1.高速缓存
随着工艺技术的发展处理器的运算速度和内存容量按摩尔定律的预测指数增加但内存速度提高非常缓慢与处理器速度的提高形成了“剪刀差”。工艺技术的上述特点使得访存延迟成为以存储器为中心的冯·诺依曼结构的主要瓶颈。Cache技术利用程序访问内存的时间局部性一个单元如果当前被访问则近期很有可能被访问和空间局部性一个单元被访问后与之相邻的单元也很有可能被访问使用速度较快、容量较小的Cache临时保存处理器常用的数据使得处理器的多数访存操作可以在Cache上快速进行只有少量访问Cache不命中的访存操作才访问内存。
Cache是内存的映像其内容是内存内容的子集处理器访问Cache和访问内存使用相同的地址。从20世纪80年代开始RISC处理器就开始在处理器芯片内集成KB级的小容量Cache。现代处理器则普遍在片内集成多级Cache典型的多核处理器的每个处理器核中一级指令Cache和数据Cache各几十KB二级Cache为几百KB而多核共享的三级Cache为几MB到几十MB。现代处理器访问寄存器时一拍可以同时读写多个数据访问一级Cache延迟为1-4拍访问二级Cache延迟为10-20拍访问三级Cache延迟为40-60拍访问内存延迟为100-200拍。
CPU执行一个程序的时间可以描述为程序运行的总动态指令数 * CPI * 时钟周期。其中CPICycle Per Instruction表示平均每条指令执行花费的时钟周期数。CPI可以进一步细分为每种类型指令的CPI与这类指令占总指令数比例乘积之和如运算指令CPI * 运算指令比例 + 访存指令CPI * 访存指令比例 + 其他指令CPI * 其他指令比例。访存指令CPI也称为平均访问延迟AMATAverage Memory Access Latency。在具有高速缓存的计算机中
$$AMAT = HitTime + MissRate * MissPenalty$$
其中HitTime表示高速缓存命中时的访问延迟MissRate表示高速缓存失效率MissPenalty表示高速缓存失效时额外的访问延迟。例如在某计算机系统中HitTime=1, MissRate=5%, MissPenalty=100则AMAT=1+5=6。
2.内存
主存储器又称为内存。内存的读写速度对计算机的整体性能影响重大。为了提升处理器的访存性能现代通用处理器都将内存控制器与CPU集成在同一芯片内以减小平均访存延迟。
现代计算机的内存一般都采用同步动态随机存储器SDRAM实现。DRAM的一个单元由MOS管T和电容C存储单元组成如图\@ref(fig:dram-cell)所示。电容C存储的电位决定存储单元的逻辑值。单元中的字线根据读写地址译码得到连接同一字的若干位单元中的位线把若干字的同一位链接在一起。进行读操作时先把位线预充到Vref=VCC/2然后字线打开T管C引起差分位线微小的电位差感应放大器读出读出后C中的电位被破坏需要把读出值重新写入C。进行写操作时先把位线预充成要写的值然后打开字线把位线的值写入C。C中的电容可能会漏掉因此DRAM需要周期刷新刷新可以通过读操作进行一般每行几十微秒刷新一次。
"
```{r dram-cell, echo=FALSE, fig.align='center', fig.cap="DRAM的单元读写原理", out.width='50%'}
knitr::include_graphics("images/chapter5/dram_cell.png")
```
SDRAM芯片一般采用行列地址线复用技术对SDRAM进行读写时需要先发送行地址打开一行再发送列地址读写需要访问的存储单元。为了提高访问的并发度SDRAM芯片一般包含多个Bank存储块这些Bank可以并行操作。图\@ref(fig:sdram-structure)显示了一个DDR2 SDRAM x8芯片的内部结构图。可以看到该SDRAM内部包含了8个Bank每个Bank对应一个存储阵列和一组感应放大器所有的Bank共用读锁存Read Latch和写FIFO。
对SDRAM进行写操作后由于必须等到写数据从IO引脚传送到对应Bank的感应放大器后才能进行后续的预充电操作针对相同Bank或者读操作针对所有Bank因此写操作会给后续的其他操作带来较大的延迟但连续的写操作却可以流水执行。为了降低写操作带来的开销内存控制器往往将多个写操作聚集在一起连续发送以分摊单个写操作的开销。
```{r sdram-structure, echo=FALSE, fig.align='center', fig.cap="SDRAM的功能结构图", out.width='100%'}
knitr::include_graphics("images/chapter5/sdram_structure.png")
```
影响SDRAM芯片读写速度的因素有两个行缓冲局部性Row Buffer Locality简称RBL和Bank级并行度Bank Level Parallelism简称BLP
1行缓冲局部性。如图\@ref(fig:sdram-structure)所示SDRAM芯片的一行数据在从存储体中读出后存储体中的值被破坏保存在对应的一组感应放大器中这组感应放大器也被称为行缓冲。如果下一个访存请求访问同一行的数据称为命中行缓冲可以直接从该感应放大器中读出而不需要重新访问存储体内部可以大大降低SDRAM的访问延迟。当然在行缓冲不命中的时候就需要首先将行缓冲中的数据写回存储体再将下一行读出到行缓冲中进行访问。由此对DRAM可以采用关行Close Page和开行Open Page两种策略。使用关行策略时每次读写完后先把行缓冲的内容写入存储体才能进行下一次读写每次读写的延迟是确定的。使用开行策略时每次读写完后不把行缓冲的内容写入存储体如果下一次读写时所读写的数据在行缓冲中称为行命中可以直接对行缓冲进行读写即可延迟最短如果下一次读写时所读写的数据不在行缓冲中则需要先将行缓冲中的数据写回对应的行再将新地址的数据读入行缓冲再进行读写延迟最长。因此如果内存访问的局部性好可以采用开行策略如果内存访问的局部性不好则可以采用关行策略。内存控制器可以通过对多个访存请求进行调度尽量把对同一行的访问组合在一起以增加内存访问的局部性。
2Bank级并行度。SDRAM芯片包含的多个Bank是相互独立的它们可以同时执行不同的操作比如对Bank 0激活的同时可以对Bank 1发出预充电操作因此访问不同Bank的多个操作可以并行执行。Bank级并行度可以降低冲突命令的等待时间容忍单个Bank访问的延迟。
利用内存的这两个特性,可以在内存控制器上对并发访问进行调度,尽可能降低读写访问的平均延迟,提高内存的有效带宽。内存控制器可以对十几甚至几十个访存请求进行调度,有效并发的访存请求数越多,可用于调度的空间就越大,可能得到的访存性能就更优。
### 输入/输出设备
输入/输出设备简称IO设备实现计算机与外部世界的信息交换。传统的IO设备有键盘、鼠标、打印机和显示器等新型的IO设备能进行语音、图像、影视的输入、输出和手写体文字输入并支持计算机之间通过网络进行通信。磁盘等辅助存储器在计算机中也当作IO设备来管理。
处理器通过读写IO设备控制器中的寄存器来访问及控制IO设备。高速IO设备可以在处理器安排下直接与主存储器成批交换数据称为直接存储器访问Directly Memory Access简称DMA。处理器可以通过查询设备控制器状态与IO设备进行同步也可以通过中断与IO设备进行同步。
下面以GPU、硬盘和闪存为例介绍典型的IO设备。
**1GPU**
GPUGraphics Processing Unit图形处理单元是与CPU联系最紧密的外设之一主要用来处理2D和3D的图形、图像和视频以支持基于视窗的操作系统、图形用户界面、视频游戏、可视化图像应用和视频播放等。
当我们在电脑上打开播放器观看电影时GPU负责将压缩后的视频信息解码为原始数据并通过显示控制器显示到屏幕上当我们拖动鼠标移动一个程序窗口时GPU负责计算移动过程中和移动后的图像内容当我们玩游戏时GPU负责计算并生成游戏画面。
GPU驱动提供OpenGL、DirectX等应用程序编程接口以方便图形编程。其中OpenGL是一个用于3D图形编程的开放标准DirectX是微软公司推出的一系列多媒体编程接口包括用于3D图形的Direct3D。通过这些应用程序接口软件人员可以很方便地实现功能强大的图形处理软件而不必关心底层的硬件细节。
GPU最早是作为一个独立的板卡出现的所以称为显卡。我们常说的独立显卡和集成显卡是指GPU是作为一个独立的芯片出现还是被集成在芯片组或处理器中。现代GPU内部包含了大量的计算单元可编程性越来越强除了用于图形图像处理外也越来越多地用作高性能计算的加速部件称为加速卡。
GPU与CPU之间存在大量的数据传输。CPU将需要显示的原始数据放在内存中让GPU通过DMA的方式读取数据经过解析和运算将结果写至显存中再由显示控制器读取显存中的数据并输出显示。将GPU与CPU集成至同一个处理器芯片时CPU与GPU内存一致性维护的开销和数据传递的延迟都会大幅降低。此时系统内存需要承担显存的任务访存压力也会大幅增加因为图形应用具有天生的并行性GPU可以轻松地耗尽有限的内存带宽。
GPU的作用是对图形API定义的流水线实现硬件加速主要包括以下几个阶段
- 顶点读入Vertex Fetch从内存或显存中取出顶点信息包括位置、颜色、纹理坐标、法向量等属性
- 顶点渲染Vertex Shader对每一个顶点进行坐标和各种属性的计算
- 图元装配Primitive Assembly将顶点组合成图元如点、线段、三角形等
- 光栅化Rasterization将矢量图形点阵化得到被图元覆盖的像素点并计算属性插值系数以及深度信息
- 像素渲染Fragment Shader进行属性插值计算每个像素的颜色
- 逐像素操作Per-Fragment Operation进行模板测试、深度测试、颜色混合和逻辑操作等并最终修改渲染缓冲区
在GPU中集成了专用的硬件电路来实现特定功能同时也集成了大量可编程的计算处理核心用于一些较为通用的功能实现。设计者根据每个功能使用的频率、方法以及性能要求选择不同的实现方式。大部分GPU中顶点读入、图元装配、光栅化及逐像素操作使用专用硬件电路实现而顶点渲染和像素渲染采用可编程的计算处理核心实现。由于现代GPU中集成了大量可编程的计算处理核心这种大规模并行的计算模式非常适合于科学计算应用所以在高性能计算机领域GPU常被用作计算加速单元配合CPU使用。
**2.硬盘**
计算机除了需要内存存放程序的中间数据外,还需要具有永久记忆功能的存储体来存放需要较长时间保存的信息。比如操作系统的内核代码、文件系统、应用程序和用户的文件数据等。该存储器除了容量必须足够大之外,价格还要足够便宜,同时速度还不能太慢。在计算机的发展历史上,磁性存储材料正好满足了以上要求。磁性材料具有断电记忆功能,可以长时间保存数据;磁性材料的存储密度高,可以搭建大容量存储系统;同时,磁性材料的成本很低。
人们目前使用的硬盘就是一种磁性存储介质。硬盘的构造原理为将磁性材料覆盖在圆形碟片或者说盘片通过一个读写头磁头悬浮在碟片表面来感知存储的数据。通过碟片的旋转和磁头的径向移动来读写碟片上任意位置的数据。碟片被划分为多个环形的轨道称为磁道Track来保存数据每个磁道又被分为多个等密度等密度数据的弧形扇区Sector作为存储的基本单元。磁盘的内部构造如图\@ref(fig:disk-structure)所示。硬盘在工作时,盘片是一直旋转的,当想要读取某个扇区的数据时,首先要将读写头移动到该扇区所在的磁道上,当想要读写的扇区旋转到读写头下时,读写头开始读写数据。
```{r disk-structure, echo=FALSE, fig.align='center', fig.cap="磁盘的内部结构图", out.width='50%'}
knitr::include_graphics("images/chapter5/disk_structure.png")
```
衡量磁盘性能的指标包括响应时间和吞吐量也就是延迟和带宽。磁头移动到目标磁道的时间称为寻道时间。当磁头移动到目标磁道后需要等待目标扇区旋转到磁头下面这段时间称为旋转时间。旋转时间与盘片的旋转速度有关磁盘的旋转速度用RPMRotation Per Minute转/分来表示我们常说的5400转、7200转就是指磁盘的旋转速度。扇区旋转到目标位置后传输这个扇区的数据同样需要时间称为传输时间。传输时间是扇区大小、旋转速度和磁道记录密度的函数。
磁盘是由磁盘控制器控制的。磁盘控制器控制磁头的移动、接触和分离以及磁盘和内存之间的数据传输。另外通过IO操作访问磁盘控制器又会引入新的时间。现在的磁盘内部一般都会包含一个数据缓冲读写磁盘时如果访问的数据正好在缓冲中命中则不需要访问磁盘扇区。还有当有多个命令读写磁盘时还需要考虑排队延迟。因此磁盘的访问速度计算起来相当复杂。一般来说磁盘的平均存取时间在几个毫秒的量级。
磁盘的密度一直在持续增加对于用户来说磁盘的容量一直在不断增大。磁盘的尺寸也经历了一个不断缩小的过程从最大的14英寸1英寸=0.0254米到最小的1.8英寸。目前市场上常见的磁盘尺寸包括应用于台式机的3.5英寸和应用于笔记本电脑的2.5英寸。
**3.闪存**
闪存Flash Storage是一种半导体存储器它和磁盘一样是非易失性的存储器但是它的访问延迟却只有磁盘的千分之一到百分之一而且它尺寸小、功耗低抗震性更好。常见的闪存有SD卡、U盘和SSD固态磁盘等。与磁盘相比闪存的每GB价格较高因此容量一般相对较小。目前闪存主要应用于移动设备中如移动电话、数码相机、MP3播放器主要原因在于它的体积较小。闪存在移动市场具有很强的应用需求工业界投入了大量财力推动闪存技术的发展。随着技术的发展闪存的价格在快速下降容量在快速增加因此SSD固态硬盘技术获得了快速发展。SSD固态硬盘是使用闪存构建的大容量存储设备它模拟硬盘接口可以直接通过硬盘的SATA总线与计算机相连。
最早出现的闪存被称为NOR型闪存因为它的存储单元与一个标准的或非门很像。NAND型闪存采用另一种技术它的存储密度更高每GB的成本更低因此NAND型闪存适合构建大容量的存储设备。前面所列的SD卡、U盘和SSD固态硬盘一般都是用NAND型闪存构建的。
使用闪存技术构建的永久存储器存在一个问题即闪存的存储单元随着擦写次数的增多存在损坏的风险。为了解决这个问题大多数NAND型闪存产品内部的控制器采用地址块重映射的方式来分布写操作目的是将写次数多的地址转移到写次数少的块中。该技术被称为磨损均衡Wear Leveling。闪存的平均擦写次数在10万次左右。这样通过磨损均衡技术移动电话、数码相机、MP3播放器等消费类产品在使用周期内就不太可能达到闪存的写次数限制。闪存产品内部的控制器还能屏蔽制造过程中损坏的块从而提高产品的良率。
## 计算机系统硬件结构发展
前面章节从冯·诺依曼结构出发,介绍了现代计算机的理论结构及其组成部分。随着应用需求的变化和工艺水平的不断提升,冯·诺依曼结构中的控制器和运算器逐渐演变为计算机系统中的中央处理器部分,而输入、输出设备统一通过北桥和南桥与中央处理器连接,中央处理器中的图形处理功能则从中央处理器中分化出来形成专用的图形处理器。因此,现代计算机系统的硬件结构主要包括了中央处理器、图形处理器、北桥及南桥等部分。
**中央处理器**Central Processing Unit简称CPU主要包含控制器和运算器在发展的过程中不断与其他部分融合。传统意义上的中央处理器在处理器芯片中更多地体现为处理器核现代的处理器芯片上往往集成多个处理器核。
**图形处理器**Graphic Processing Unit简称GPU是一种面向2D和3D图形、视频、可视化计算和显示优化的处理器。作为人机交互的重要界面GPU在计算机体系结构发展的过程中担任了越来越重要的角色。除了对图形处理本身之外还开始担负科学计算加速器的任务。
**北桥**North Bridge是离CPU最近的芯片主要负责控制显卡、内存与CPU之间的数据交换向上连接处理器向下连接南桥。
**南桥**South Bridge主要负责硬盘、键盘以及各种对带宽要求较低的IO接口与内存、CPU之间的数据交换。
### CPU-GPU-北桥-南桥四片结构
现代计算机的一种早期结构是CPU-GPU-北桥-南桥结构。在该结构中计算机系统包含四个主要芯片其中CPU处理器芯片、北桥芯片和南桥芯片一般是直接以芯片的形式安装或焊接在计算机主板上而GPU则以显卡的形式安装在计算机主板的插槽上。
在CPU-GPU-北桥-南桥四片结构中计算机的各个部件根据速度快慢以及与处理器交换数据的频繁程度被安排在北桥和南桥中。CPU通过处理器总线也称系统总线和北桥直接相连北桥再通过南北桥总线和南桥相连GPU一般以显卡的形式连接北桥。内存控制器集成在北桥芯片中硬盘接口、USB接口、网络接口、音频接口以及鼠标、键盘等接口放在南桥芯片中。此外在北桥上还会提供各种扩展接口用于其他功能卡的连接。采用该结构的微机系统如图\@ref(fig:structure-4part)所示。
```{r structure-4part, echo=FALSE, fig.align='center', fig.cap="CPU-GPU-北桥-南桥结构", out.width='50%'}
knitr::include_graphics("images/chapter5/structure_4part.png")
```
与英特尔奔腾处理器搭配的430HX芯片组就采用了这样的四片结构。其北桥芯片使用82439HX南桥芯片采用82371SB通过PCI总线扩展外接显卡与处理器组成四片结构作为计算机系统的主要部分。
### CPU-北桥-南桥三片结构
现代计算机的一种典型结构是CPU-北桥-南桥结构。在该结构中系统包含三个主要芯片分别为CPU芯片、北桥芯片和南桥芯片。三片结构与四片结构最大的区别是前者GPU功能被集成到北桥即一般所说的集成显卡。
在CPU-北桥-南桥三片结构中CPU通过处理器总线和北桥直接相连北桥再通过南北桥总线和南桥相连。内存控制器、显示功能以及高速IO接口如PCIE等集成在北桥芯片中硬盘接口、USB接口、网络接口、音频接口以及鼠标、键盘等接口部件放在南桥芯片中。随着计算机技术的发展更多的高速接口被引入计算机体系结构中在北桥上集成的IO接口的速率也不断提升。
采用该结构的微机系统如图\@ref(fig:structure-3part)所示。
```{r structure-3part, echo=FALSE, fig.align='center', fig.cap="CPU -北桥 -南桥结构", out.width='50%'}
knitr::include_graphics("images/chapter5/structure_3part.png")
```
英特尔845G芯片组就采用类似的三片结构。其北桥芯片使用82845G集成显示接口南桥芯片采用82801DB与处理器组成三片结构作为计算机系统的主要部分。
### CPU-弱北桥-南桥三片结构
随着工艺和设计水平的不断提高,芯片的集成度不断提高,单一芯片中能够实现的功能越来越复杂。内存接口的带宽需求超过了处理器与北桥之间连接的处理器总线接口,导致内存的实际访问性能受限于处理器总线的性能。而伴随着处理器核计算性能的大幅提升,存储器的性能提升却显得幅度较小,这两者的差异导致计算机系统性能受到存储器系统发展的制约,这就是存储墙问题。
因此对计算机系统性能影响显著的内存控制器开始被集成到CPU芯片中从而大幅降低了内存访问延迟提升了内存访问带宽这在一定程度上缓解了存储墙问题。
于是北桥的功能被弱化主要集成了GPU、显示接口、高速IO接口例如PCIE接口等
采用该结构的微机系统如图\@ref(fig:structure-3part-weaknb)所示。
```{r structure-3part-weaknb, echo=FALSE, fig.align='center', fig.cap="CPU -弱北桥 -南桥结构", out.width='50%'}
knitr::include_graphics("images/chapter5/structure_3part_weaknb.png")
```
相比英特尔AMD的处理器最早将内存控制器集成到处理器芯片中780E芯片组就采用上述三片结构北桥芯片使用RS780E集成HD3200 GPU南桥芯片使用SB710与处理器组成三片结构作为计算机系统的主要部分。
### CPU-南桥两片结构
在计算机系统不断发展的过程中,图形处理器性能也在飞速发展,其在系统中的作用也不断被开发出来。除了图形加速以外,对于一些科学计算类的应用,或者是一些特定的算法加速程序,图形处理器发挥着越来越大的作用,成为特定的运算加速器,其与中央处理器之间的数据共享也越来越频繁,联系越来越密切。
随着芯片集成度的进一步提高图形处理器也开始被集成到CPU芯片中于是北桥存在的必要性就进一步降低开始和南桥合二为一形成CPU-南桥结构,如图\@ref(fig:structure-2part)所示。
在这个结构中CPU芯片集成处理器核、内存控制器和GPU等主要部件对外提供显示接口、内存接口等并通过处理器总线和南桥相连。南桥芯片则包含硬盘、USB、网络控制器以及PCIE/PCI、LPC等总线接口。由于GPU和CPU都需要大量访问内存会带来一些访存冲突而且相对来说GPU对于实时性的要求更高即访存优先级会更高一些这在一定程度上会影响CPU的性能。实际上处理器中集成的GPU性能相比独立显卡中的GPU性能会稍弱。
当然也有一些两片结构是将GPU集成在南桥芯片中。这样在南桥上可以实现独立的显存供GPU使用这在某些条件下更有利于GPU性能的发挥且CPU升级时带来的开销会更小。
```{r structure-2part, echo=FALSE, fig.align='center', fig.cap="CPU - 南桥结构", out.width='50%'}
knitr::include_graphics("images/chapter5/structure_2part.png")
```
### SoC单片结构
片上系统System on Chip简称SoC是一种单片计算机系统解决方案它在单个芯片上集成了处理器、内存控制器、GPU以及硬盘、USB、网络等IO接口使得用户搭建计算机系统时只需要使用单个主要芯片即可如图\@ref(fig:soc)所示。
```{r soc, echo=FALSE, fig.align='center', fig.cap="SOC单片结构", out.width='50%'}
knitr::include_graphics("images/chapter5/soc.png")
```
目前SoC主要应用于移动处理器和工业控制领域相比上述几种多片结构单片SoC结构的集成度更高功耗控制方法更加灵活有利于系统的小型化和低功耗设计。但也因为全系统都在一个芯片上实现导致系统的扩展性没有多片结构好升级的开销也更大。随着技术的发展封装基板上的互连技术不断发展和成熟。越来越多的处理器利用多片封装技术在单个芯片上集成多个硅片以扩展芯片的计算能力或IO能力。例如AMD Ryzen系列处理器通过在封装上集成多个处理器硅片和IO硅片以提供针对不同应用领域的计算能力。龙芯3C5000L处理器则通过在封装上集成4个4核龙芯3A5000硅片来实现单片16核结构。
目前主流商用处理器中面向中高端领域的处理器普遍采用两片结构而面向中低端及嵌入式领域的处理器普遍采用单片结构。SoC单片结构最常见的是在手机等移动设备中。
## 处理器和IO设备间的通信
前面介绍了组成计算机系统的各个部分,在冯·诺依曼结构中,处理器(准确地说是内部的控制器)处于中心位置,需要控制其他各个部件的运行。
对存储器的控制是通过读写指令来完成的。存储器是存储单元阵列,对某个地址的读写不会影响其他存储单元。
而IO设备大都是具有特定功能的部件不能当作简单的存储阵列来处理。由于IO设备的底层控制相当复杂它们一般都是由一个设备控制器进行控制。设备控制器会提供一组寄存器接口寄存器的内容变化会引起设备控制器执行一系列复杂的动作。设备控制器的接口寄存器也被称为IO寄存器。处理器通过读写IO寄存器来访问设备。写入这些寄存器的数据会被设备控制器解析成命令因此有些情况下将处理器对IO寄存器的访问称为命令字。处理器对内存和IO的访问模式有所不同对访问的延迟和带宽需求也有较大差异。现代计算机系统的程序和数据都存放在内存中内存访问性能直接影响处理器流水线的执行效率也正是因为这样才导致了各个Cache层次的出现。对处理器的内存访问来说要求是高带宽和低延迟。IO设备一般用于外部交互而IO操作一般会要求顺序的访问控制从而导致执行效率低下访问带宽低延迟高只能通过IO的DMA操作来提升性能。IO的DMA操作也是访问内存因为DMA访存模式一般是大块的连续数据读写所以对带宽的需求远高于对延迟的需求。
### IO寄存器寻址
为了访问IO寄存器处理器必须能够寻址这些寄存器。IO寄存器的寻址方式有两种内存映射IO和特殊IO指令。
内存映射IO是把IO寄存器的地址映射到内存地址空间中这些寄存器和内存存储单元被统一编址。读写IO地址和读写内存地址使用相同的指令来执行。处理器需要通过它所处的状态来限制应用程序可以访问的地址空间使其不能直接访问IO地址空间从而保证应用程序不能直接操作IO设备。与内存映射IO不同特殊IO指令使用专用指令来执行IO操作。因此IO地址空间可以和内存地址空间重叠但实际指向不同的位置。操作系统可以通过禁止应用程序执行IO指令的方式来阻止应用程序直接访问IO设备。MIPS或LoongArch结构并没有特殊IO指令通过普通的访存指令访问特定的内存地址空间进行IO访问。而X86结构使用专门的IO指令来执行IO操作。
### 处理器和IO设备之间的同步
处理器和IO设备之间需要协同工作通过一系列软件程序来共同发挥设备功能。处理器和IO设备之间的同步有两种方式查询和中断。
处理器通过向IO寄存器写入命令字来控制IO设备。大部分的控制操作不是通过一次寄存器写入就能完成的处理器一般需要对IO寄存器进行多次访问才能完成一次任务。绝大多数设备的IO寄存器不是无条件写入的处理器在写入命令字之前先要获取设备的当前状态只有当设备进入特定的状态后处理器才能执行特定的操作这些特定的软件操作流程是在驱动程序中实现的。比如对于一台打印机打印机控制器会提供两个寄存器数据寄存器和状态寄存器。数据寄存器用来存放当前需要打印的数据状态寄存器用来指示打印机的状态它包含两个基本位完成位和错误位。完成位表示上一个字符打印完毕可以打印下一个字符错误位用来在打印机出现异常时指示出错的状态比如卡纸或者缺纸。处理器在打印一串数据时首先把数据写入数据寄存器然后不断读取状态寄存器的值当读出的完成位等于1时才能把下一个字符写入数据寄存器。同时处理器还需要检查错误位的值当发生错误时去执行对应的错误处理程序。
前面描述的打印过程就是查询方式的一个例子。当使用查询方式时处理器向IO设备发出访问请求后需要不断读取IO设备的状态寄存器所以查询方式也被称为轮询。由于IO设备的速度一般都较慢使用查询方式会浪费处理器的指令周期。而且执行轮询的处理器无法同时执行其他工作造成了性能的浪费。
为了解决查询方式效率较低的问题中断方式被引入计算机系统。在中断方式下处理器不需要轮询状态寄存器的值而是在等待设备完成某个操作时转去执行其他进程。当设备完成某个操作后自行产生一个中断信号来中断处理器的执行。处理器被中断后再去读取设备的状态寄存器。中断方式将处理器从等待IO中解放了出来大大提高了处理器的利用率因此现代计算机的绝大部分IO设备都支持中断方式。
中断本质上是IO设备对处理器发出的一个信号让处理器知道此时有数据传输需要或者已经发生数据传输。CPU收到中断信号后会暂停当前CPU的执行进程转去执行某个特定的程序。中断的一般过程为
1中断源发出中断信号到中断控制器
2中断控制器产生中断请求给CPU
3CPU发出中断响应并读取中断类型码
4CPU根据中断类型码执行对应的中断服务程序
5CPU从中断服务程序返回中断结束。
中断源即中断的源头比如用户敲击一下键盘单击一下鼠标或者DMA的一次传输完成了对应的控制器会产生一个中断信号。中断信号可以是一根信号线也可以是一个消息包。这个中断信息会传送到中断控制器中。中断控制器是负责中断汇集、记录和转发的硬件逻辑。中断控制器一般都具有可编程功能因此被称为可编程中断控制器Programmable Interrupt Controller简称PIC。典型的中断控制器如Intel的8259A。8259A支持中断嵌套和中断优先级可以支持8个中断源并可以通过级联的方式进行扩展。
8259A内部包含3个寄存器中断请求寄存器(Interrupt Request Register简称IRR),用来存放当前的中断请求;中断在服务寄存器(In-Service Register简称ISR)用来存放当前CPU正在服务的中断请求中断Mask寄存器(Interrupt Mask Register简称IMR),用来存放中断屏蔽位。
当中断源产生中断信号后会将中断请求寄存器的某一位设置为1如果该位没有被屏蔽则产生一个中断信号比如中断线给处理器。处理器检测到该中断信号并跳转到固定的地址执行中断服务例程。在中断服务例程中处理器通过读取8259A获得中断向量号进而调用对应的中断服务程序。在中断服务程序返回之前要保证本次中断的中断信号被清除掉否则CPU从中断服务程序返回之后会被再次触发中断。8259A在中断响应时会自动将IRR的对应位复位。对于电平触发的中断中断服务程序一般会读写中断源的相关寄存器从而保证在中断返回之前中断源的中断信号被撤掉这样8259A的中断请求寄存器的对应位不会被再次置位。对于脉冲触发的中断则不需要对设备IO寄存器进行处理。
### 存储器和IO设备之间的数据传送
存储器和IO设备之间需要进行大量的数据传输。例如系统在启动时需要把操作系统代码从硬盘搬运到内存中计算机想要输出图形时需要把准备显示的数据从内存搬运到显示控制器中。
那么存储器和IO设备之间是如何进行数据交换的呢
早期存储器和IO设备之间的数据传送都是由处理器来完成的。由于存储器和IO设备之间没有直接的数据通路当需要从存储器中搬运数据到IO设备时处理器首先从存储器中读数据到通用寄存器中再从通用寄存器写数据到IO设备中当需要从IO设备搬运数据到存储器中时处理器要先从IO设备中读数据到通用寄存器再从通用寄存器写入内存。这种方式称为PIOProgramming Input/Output模式。
由于IO访问的访问延迟一般较大而且IO访问之间需要严格的顺序关系因而PIO方式的带宽较低。PIO模式存在两种同步方式查询方式和中断方式。虽然中断方式可以降低处理器查询的开销但当进行大量数据传输时PIO模式仍然需要占用大量的处理器时间。使用中断方式每传送一定的数据后都要进入一次中断在中断服务程序中真正用于数据传送的时间可能并不多大量的时间被用于断点保护、中断向量查询、现场恢复、中断返回等辅助性工作。对于一些数据传送速率较快的设备PIO方式可能会因为处理器搬运数据速度较慢而降低数据的传送速度因此PIO方式一般用于键盘、鼠标等低速设备。
在PIO方式中数据要经过处理器内部的通用寄存器进行中转。中转不仅影响处理器的执行也降低了数据传送的速率。如果在存储器和IO设备之间开辟一条数据通道专门用于数据传输就可以将处理器从数据搬运中解放出来。这种方式就是DMADirect Memory Access直接存储器访问方式。DMA方式在存储器和外设之间开辟直接的数据传送通道数据传送由专门的硬件来控制。控制DMA数据传送的硬件被称为DMA控制器。
使用DMA进行传输的一般过程为
1处理器为DMA请求预先分配一段地址空间。
2处理器设置DMA控制器参数。这些参数包括设备标识、数据传送的方向、内存中用于数据传送的源地址或目标地址、传输的字节数量等。
3DMA控制器进行数据传输。DMA控制器发起对内存和设备的读写操作控制数据传输。DMA传输相当于用IO设备直接读写内存。
4DMA控制器向处理器发出一个中断通知处理器数据传送的结果成功或者出错以及错误信息
5处理器完成本次DMA请求可以开始新的DMA请求。
DMA方式对于存在大量数据传输的高速设备是一个很好的选择硬盘、网络、显示等设备普遍都采用DMA方式。一个计算机系统中通常包含多个DMA控制器比如有特定设备专用的SATA接口DMA控制器、USB接口DMA控制器等也有通用的DMA控制器用于可编程的源地址与目标地址之间的数据传输。
DMA控制器的功能可以很简单也可以很复杂。例如DMA控制器可以仅仅支持对一段连续地址空间的读写也可以支持对多段地址空间的读写以及执行其他的IO操作。不同的IO设备的DMA行为各不相同因此现代的IO控制器大多会实现专用的DMA控制器用于自身的数据传输。
表\@ref(tab:pio-vs-dma)举例说明了PIO和DMA两种数据传输方式的不同。
```{r pio-vs-dma, echo = FALSE, message=FALSE, tab.cap='PIO和DMA两种数据传输方式'}
autonum <- run_autonum(seq_id = "tab", bkm = "pio-vs-dma", bkm_all = TRUE)
readr::read_csv('./materials/chapter5/pio_vs_dma.csv') %>%
flextable() %>%
set_caption(caption="PIO和DMA两种数据传输方式", autonum = autonum) %>%
width(j=1, width=2.5) %>%
width(j=2, width=3.5) %>%
theme_box()
```
上面两个例子中可以看到PIO方式和DMA方式处理的流程一致区别在于首先键盘的数据是被记录在IO设备本身的而网卡的数据则直接由网卡写入内存之中其次CPU处理时对键盘是直接从IO寄存器读数据而对网卡则直接从内存读数据。
看起来似乎差别不大。但需要考虑的是IO访问相比内存访问慢很多而且对于内存访问CPU可以通过Cache、预取等方式进行加速IO访问则缺少这种有效的优化方式。在上面的例子中如果网卡采用PIO的方式使用CPU对网卡的包一个字一个字地进行读访问效率将非常低下。而对于键盘来说一次输入仅仅只有8位数据而且相比处理器的处理速度键盘输入的速度相当低采用PIO的处理方式能够很简单地完成数据输入任务。
### 龙芯3A3000+7A1000桥片系统中的CPU、GPU、DC通信
下面以龙芯3A3000+7A1000桥片中CPU、GPU、DC间的同步与通信为例说明处理器与IO间的通信。如图\@ref(fig:loongson-3A3000)所示龙芯3A3000处理器和龙芯7A1000桥片通过HyperTransport总线相连7A1000桥片中集成GPU、DC显示控制器以及专供GPU和DC使用的显存控制器。CPU可以通过PIO方式读写GPU中的控制寄存器、DC中的控制寄存器以及显存GPU和DC可以通过DMA方式读写内存GPU和DC还可以读写显存。
```{r loongson-3A3000, echo=FALSE, fig.align='center', fig.cap="龙芯3A3000+7A1000两片方案", out.width='50%'}
knitr::include_graphics("images/chapter5/loongson_3A3000.png")
```
CPU或GPU周期性地把要显示的数据写入帧缓存Frame BufferDC根据帧缓存的内容进行显示。帧缓存可以分配在内存中GPU和DC通过DMA方式访问内存中的帧缓存在独立显存的情况下帧缓存分配在独立显存中CPU直接把要显示的数据写入帧缓存或者GPU通过DMA方式从内存中读取数据并把计算结果写入帧缓存DC直接读取帧缓存的内容进行显示。根据是否由GPU完成图形计算以及帧缓存是否分配在内存中常见的显示模式有以下四种。
模式一不使用GPUCPU与DC共享内存。不使用桥片上的显存而在内存中分配一个区域专供显示使用这个区域称之为帧缓存framebuffer。需要显示时CPU通过正常内存访问将需要显示的内容写入内存中的帧缓存然后通过PIO方式读写DC中的控制寄存器启动DMADC通过DMA操作读内存中的帧缓存并进行显示如图\@ref(fig:3A3000-display)a所示。
模式二不使用GPUDC使用独立显存。DC使用桥片上的显存这个区域称之为帧缓存。需要显示时CPU将需要显示的内容从内存读出再通过PIO方式写入独立显存上的帧缓存然后通过PIO操作读写DC中的控制寄存器启动DMADC读显存上的帧缓存并进行显示如图\@ref(fig:3A3000-display)b所示。
模式三CPU与GPU/DC共享内存。需要显示时CPU在内存中分配GPU使用的空间并将相关数据填入然后CPU通过PIO读写GPU中的控制寄存器启动DMA操作GPU通过DMA读内存并将计算结果通过DMA写入内存中的帧缓存CPU通过PIO方式读写DC中的控制寄存器启动DMADC通过DMA方式读内存中的帧缓存并完成显示如图\@ref(fig:3A3000-display)c所示。
模式四GPU/DC使用独立显存。需要显示时CPU在内存中分配GPU使用的空间并将相关数据填入然后CPU通过PIO读写GPU中的控制寄存器启动DMA操作GPU通过DMA读内存并将计算结果写入显存中的帧缓存DC读显存中的帧缓存并完成显示如图\@ref(fig:3A3000-display)d所示。
```{r 3A3000-display, echo=FALSE, fig.align='center', fig.cap="3A3000+7A1000的不同显示方式", out.width='100%'}
knitr::include_graphics("images/chapter5/3A3000_display.png")
```
## 本章小结
本章介绍了计算机系统的基本原理和硬件组成结构。冯·诺依曼结构将计算机分为控制器、运算器、存储器、输入设备和输出设备五大部分这一章重点介绍了冯·诺依曼结构组成部分的结构及各部分之间的关系尤其是CPU、内存、IO之间的相互关系。
## 习题
1. 分别说明图\@ref(fig:structure-4part) \@ref(fig:structure-2part)中四种结构中每个芯片包含冯·诺依曼结构五个部分的哪部分功能。
2. 查阅资料比较Skylake处理器和Zen处理器的运算器结构。
3. 说明ROB、保留站发射队列、重命名寄存器在指令流水线中的作用并查阅资料比较Skylake处理器和Zen处理器的ROB、发射队列、重命名寄存器项数。
4. 假设A处理器有两级Cache一级Cache大小为32KB命中率为95%命中延迟为1拍二级Cache大小为1MB命中率为80%命中延迟为30拍失效延迟为150拍。B处理器有三级Cache一级Cache大小为32KB命中率为95%命中延迟为1拍二级Cache大小为256KB命中率为75%命中延迟为20拍三级Cache大小为4MB命中率为80%命中延迟为50拍失效延迟为150拍。比较两款处理器的平均访问延迟。
5. 假设某内存访问行关闭、打开、读写各需要两拍在行缓存命中率为70%和30%的情况下采用open page模式还是close page模式性能更高
6. 简要说明处理器和IO设备之间的两种通信方式的通信过程。
7. 简要说明处理器和IO设备之间的两种同步方式的同步过程。
8. 在一个两片系统中CPU含内存控制器桥片含GPU、DC和显存简要说明在PPT翻页过程中CPU、GPU、DC、显存、内存之间的同步和通信过程。
9. 调查目前市场主流光盘、硬盘、SSD盘、内存的价格并计算每GB存储容量的价格。
\newpage