计算机体系结构这门课,很多人第一反应是“背知识点”,第二反应是“算CPI”。我在山大把这门课完整啃下来之后发现,它其实是整个计算机专业里最讲“权衡”的一门课——没有绝对的最优,只有针对某个目标的取舍。这篇知识点清单就是我当时复习时梳理的主线,照着这个框架去理解胡伟武老师那本《计算机体系结构教学与习题指导(第2版)》,会比零散刷题高效得多。内容覆盖性能计算、指令集、流水线、存储层次、多处理器这几大板块,既有概念辨析,也有计算套路,适合期末复习、考研复试和自学入门的人参考。
1. 先搭框架:计算机体系结构这门课到底在讲什么
1.1 体系结构与计算机组成、微架构的边界
很多同学第一节课就被三个名词搞晕:体系结构、计算机组成、微架构。我当初也糊涂了很久,后来用一个比喻才彻底分清。体系结构(ISA)是“软件能看到的计算机”,相当于一份合同,约定好了有哪些指令、寄存器怎么编号、数据怎么寻址;而微架构是“硬件怎么实现这份合同”,相当于你在合同约束下用电路把功能造出来。同一个ISA可以有不同的微架构实现,就像同一份菜谱,不同厨师做出来的口味可能不一样,但最终端上桌的菜名是一样的。
山东大学的体系结构课程是放在计算机科学与技术专业大三开设的,用的教材是胡伟武老师的《计算机体系结构教学与习题指导(第2版)》,这本书和国内很多高校用的经典英文教材思路不太一样,它更强调“从应用需求出发看设计”,并且大量使用MIPS作为教学指令集。学这门课之前最好已经修过数字逻辑和计算机组成原理,否则流水线那一章的单周期/多周期数据通路会让你怀疑人生。如果还没学过组成原理直接上了体系结构,也不用慌,但一定要把“指令是怎么样一步一步被执行”这个基本动作补上。
1.2 贯穿全书的定量分析原则与八个思想
胡伟武教材的第一章不是直接讲硬件,而是先讲方法论。这里有两个东西一定要吃透,后面所有章节都会反复用到。第一个是定量分析原则:不能只说“这个设计更快”,而是要说“快了百分之多少”,所以性能公式和Amdahl定律是第一章的重点。第二个是八个伟大思想,分别是:面向摩尔定律的设计、使用抽象简化设计、加速大概率事件、通过并行提高性能、通过流水线提高性能、通过预测提高性能、存储层次、通过冗余提高可靠性,这八个思想在后面每一章都会以具体技术形态出现。
我复习的时候习惯把这八个思想抄在一张纸上,每学完一章就回去看看这章对应哪个思想。比如Cache对应存储层次和加速大概率事件,分支预测对应通过预测提高性能,这种“思想-技术”的对应关系,考试时写论述题非常好用,也是胡伟武教材和国外教材最大的不同——他喜欢让你“讲道理”,而不是单纯默写定义。
2. 性能计算是地基:CPU性能公式与Amdahl定律
2.1 CPU性能公式:CPI、主频、指令数三者的关系
性能计算是几乎每份试卷第一道大题的固定考点。核心公式就一个:
CPU时间 = 指令数 × CPI × 时钟周期时间
也可以写成 CPU时间 = 指令数 × CPI / 主频。这里最容易混淆的是“时钟周期时间”和“主频”互为倒数,1GHz主频对应1纳秒的时钟周期。做题时先看单位,别把纳秒和GHz直接相乘,这是新手最常见的错误。
还有两个派生公式要会推:MIPS(每秒百万条指令)= 主频 / (CPI × 10^6),但这个指标有个坑,它在不同指令集的机器之间没有可比性,因为指令完成的工作量不一样。考试如果让你比较两台机器性能,优先用CPU时间,实在要比较MIPS也要先说明前提。另一个是时钟周期数 = 指令数 × CPI,如果要计算多个指令类型的混合CPI,就用加权平均:总CPI = Σ(某类指令占比 × 该类指令CPI)。
举个我当年做过的真题例子:某程序包含算术运算指令100万条(CPI=1)、访存指令50万条(CPI=2)、分支指令20万条(CPI=3),主频2GHz。算下来总CPI = (100×1 + 50×2 + 20×3) / 170 = 260/170 ≈ 1.53,CPU时间 = 170万 × 1.53 / 2G ≈ 1.3毫秒。这类题关键是把“指令条数”和“占比”先分清楚,混合物不要直接算数平均。
2.2 Amdahl定律:加速比计算的套路与陷阱
Amdahl定律说的是:对系统某一部分加速,整体加速比受限于该部分原本占用的时间比例。公式是:
加速比 = 1 / [(1 - F) + F / S]
其中F是可加速部分原来的时间占比,S是该部分加速后的倍数。这个公式最重要的含义是:即使你把某个部分加速到无穷大(S→∞),整体加速比也只能到1/(1-F)。比如一个程序70%的时间花在浮点运算上,你把浮点运算加速了10倍,整体加速比 = 1/(0.3 + 0.7/10) = 1/0.37 ≈ 2.7倍。如果浮点加速到无穷大,最多也只有1/0.3 ≈ 3.33倍。
考试陷阱一般出在两个地方。一是F到底指“占总执行时间的比例”还是“是指令数量的比例”,Amdahl定律里F必须是时间占比,用指令数占比直接代进去是错的。二是题目经常给出“加速后该部分占比变了”这类干扰描述,记住公式里的F用的是原始时间占比,不需要重新归一化。
2.3 两道典型计算题的完整推导
复习的时候我整理了两类必练题型。第一类是“改进前后性能对比”,比如某个处理器的乘法指令原来占执行时间20%,把乘法改成硬件实现后,乘法时间降为原来的1/5,问整体提速多少。这里F=0.2,S=5,带入公式得加速比=1/(0.8+0.2/5)=1/0.84≈1.19倍。第二类是“求F或S的反向题”,比如已知整体加速比要达到1.5倍,某个部件加速了4倍,问这个部件原来占的时间比例是多少。解方程1.5 = 1/[(1-F)+F/4],解得F = 2/3 ≈ 66.7%。这类反向题是山大历年喜欢出的,解的时候注意把分数化成小数再验算一遍,别算完就扔。
注意:Amdahl定律里的S一定是“该部分性能提升倍数”,即原时间/新时间,千万不要倒过来算。我见过不少同学把S写成1/5然后得出负加速比,纯属符号搞反了。
3. 指令集体系结构:软件与硬件之间的契约
3.1 MIPS指令格式:R型、I型、J型怎么区分
MIPS是教学体系里最常见的ISA,胡伟武教材整本都围绕MIPS展开。MIPS指令分为三种格式,这个必须做到一眼分辨。R型指令有6位操作码opcode、5位rs、5位rt、5位rd、5位shamt(移位量)、6位funct,适用于寄存器到寄存器的运算,比如add、sub。I型指令是opcode+rs+rt+16位立即数,适用于带立即数的运算和访存指令,比如addi、lw、sw、beq。J型指令只有opcode+26位地址,用于跳转指令j。
记忆技巧是看指令带不带立即数、带不带走地址。lw/sw这类访存指令一定是I型,因为偏移量是16位立即数;beq也是I型因为需要16位偏移;而j是无条件跳转所以用J型的26位地址。考卷很喜欢让你写出某条指令的二进制编码,这时候要先把指令翻译成对应的类型,再按字段顺序逐段写,opcode和funct的编码表最好背下来,至少背熟add、addi、lw、sw、beq、j这几个高频指令的编码。
3.2 寻址方式与立即数扩展细节
MIPS的寻址方式在教材里列了大概七八种,但考试常考的是这些:寄存器寻址(操作数在寄存器)、立即数寻址、基址寻址(寄存器+16位偏移,用于lw/sw)、PC相对寻址(用于分支指令)、伪直接寻址(用于j指令)。其中PC相对寻址是个高频考点,beq的偏移量是相对于PC+4来计算的,不是相对于当前指令地址,也不是相对于下下条指令的地址?答案是要先PC+4再偏移,因为MIPS流水线取指后PC已经更新了。
立即数扩展也是易错点。addi会把16位立即数符号扩展成32位,而逻辑指令如andi、ori会做零扩展,这个区别在算负数立即数时特别明显。我复习时专门做过一道题:addi $t0, $zero, -1之后,$t0的值是多少?答案是0xFFFFFFFF,因为是符号扩展。如果换成ori $t0, $zero, 0xFFFF,$t0则是0x0000FFFF。两种扩展方式导致的结果完全不同,大题里经常让你写出寄存器最终的值,这种题就是送分题,但前提是你记得扩展方式。
3.3 RISC与CISC:为什么教材死磕MIPS
这一节概念题喜欢考RISC和CISC的对比。教材选MIPS作为教学平台,本身就是RISC设计哲学的体现:指令格式规整、指令条数少、寻址方式简单、只有load/store指令能访存、所有运算都在寄存器之间完成。CISC如x86则是变长指令、寻址方式丰富、指令可以隐式访存。两者的核心差异不是“指令多还是少”,而是设计哲学:RISC把复杂度留给编译器,硬件做简单指令;CISC把复杂度留给硬件,让指令贴近高级语言语义。
考卷里常见的一道对比题是问“为什么RISC流水线更容易实现”,答题要点有两个:一是指令长度固定,取指阶段不需要判断指令边界;二是只有load/store访存,运算指令不访问存储器,数据冒险和控制冒险的结构比较简单。另外,RISC的寄存器数量普遍较多,也是因为编译器需要更多临时值存放空间,减少访存次数。准备这种题的时候,建议自己画一张对比表格,从指令长度、指令条数、寻址方式、访存方式、执行方式五个维度列,考试时按维度逐个展开就不会丢分。
4. 流水线技术:全课分值最高的核心章节
4.1 五级流水线结构:IF/ID/EX/MEM/WB各干什么
流水线是整个体系结构课程的重头戏,期末试卷里这一章的分数经常占到三成以上。MIPS经典五级流水线分为取指(IF)、译码(ID)、执行(EX)、访存(MEM)、写回(WB)五个阶段。每一级之间由流水线寄存器隔开,这些寄存器存放上一级的中间结果。为什么要隔开?因为如果不隔开,各级电路的输入会互相干扰,前一级还没算完,后一级就拿走了错误的数据。流水线寄存器的名称IF/ID、ID/EX、EX/MEM、MEM/WB也要记清楚,画数据通路图的时候要用。
流水线提高性能的本质是把一条指令的执行拆成五段,让五条指令“重叠”执行,理想情况下每个时钟周期完成一条指令。但这只是理想,实际上因为各种冒险,流水线的实际吞吐率达不到1 IPC(每周期一条指令),这部分性能损失是后面的重点。画时序图是这章的基本功,我建议把一条lw后面紧接一条add的时序图亲手画三遍,画到能默写的程度,考试时很多分析题本质上就是在考你能不能准确画出流水线时序。
4.2 数据冒险:转发、阻塞与代码重排
数据冒险发生在两条指令存在数据依赖,而后一条指令需要的数据还没写回的时候。最经典的三类:读后写(RAW)、写后读(WAR)、写后写(WAW)。在五级流水线里,MIPS主要处理的是RAW冒险,因为WAR和WAW在五级顺序流水线中不会出现,但考试可能会问“如果改成乱序执行会出现哪些冒险”,这就需要你理解三种冒险的成因。
解决RAW冒险有三种手段,按优先级依次是:转发(bypassing)、阻塞(stall)、代码重排。转发是硬件上把后一级的计算结果直接往前送给前面需要的级,不用等写回寄存器堆。比如“add $t0, $t1, $t2; sub $t3, $t0, $t4”这两条指令,sub在ID阶段需要读$t0,而add的结果在EX阶段末尾就已经算出来了,只要在EX/MEM流水线寄存器和ID/EX之间加一条旁路,就能把结果直接喂给sub,避免阻塞。转发能消除大多数RAW冒险,但有一种情况转发解决不了:load指令后面的指令立即需要使用load出来的数据,因为load的数据要到MEM阶段结束时才能拿到,此时必须阻塞一个周期。
考试常考的题目是“给出几条指令,画出加入转发和阻塞之后的流水线时序,并算出总周期数”。做这种题我的步骤是:先标出每条指令各阶段的时间位置,再检查相邻两条指令的寄存器依赖,判断是否需要转发或阻塞,最后数周期。不要凭感觉直接写答案,画表格最稳妥。代码重排方面,教材和习题里也会让你调整指令顺序来减少阻塞,核心原则是尽量把存在依赖的指令拉开距离,让前面的指令有足够时间产生结果。
4.3 控制冒险与分支预测的关键取舍
控制冒险由分支、跳转等改变PC的指令引起。流水线在没确定分支方向之前,不能贸然取后续指令,否则可能白取。最简单的办法是“冻结流水线”,等分支结果算出来再继续,但这样每条分支指令都要浪费两个周期(MIPS分支判断在ID阶段完成)。更好的办法是分支预测:预测分支是否跳转,并提前取预测方向的指令。如果预测正确,零开销;如果预测错误,要冲刷已经进入流水线的错误指令,重新取指,浪费两个周期。
分支预测分静态和动态两类。静态预测包括“总是跳转”“总是不跳转”“根据分支方向反向预测”,胡伟武教材还提到“预测失败的比率”这个概念。动态预测则利用分支历史记录,比如1位预测器、2位预测器。2位预测器只在连续两次预测错误时才改变方向,比1位预测器的稳定度高很多,是考试常考的设计题素材。题目可能会问“一个2位饱和计数器的状态转移图怎么画”,或者“给定一串分支实际跳转结果,模拟预测器的预测正确次数”,这类题只要把状态机记熟,按步骤模拟就行。
另一个高频考点是“分支延迟槽”。MIPS体系结构里,分支指令后面的那条指令无论如何都一定会被执行,这个槽就叫延迟槽。编译器可以把有用的指令填进去,减少分支造成的流水线浪费。一套卷里如果你看到“填充分支延迟槽”的题,本质上是在考你如何在分支前后重排指令而不改变程序语义,这类题需要一点耐心,逐条检查会不会改变原有执行结果。
4.4 结构冒险与流水线性能计算
结构冒险是硬件资源冲突,比如指令取指和load/store访存同时要用存储器。MIPS教材里的解决方法是采用分离的指令存储器和数据存储器,或者使用单存储器但分时访问。这个概念相对简单,考试一般只考辨析题:“指令和数据共用一个存储器时,ld指令和后续指令之间为什么可能产生结构冒险”。
流水线性能计算的常见公式有两个。一是加速比:流水线加速比 = 非流水线总时间 / 流水线总时间,理想情况下n条指令在k级流水线上的执行时间是(n+k-1)个时钟周期,加速比趋近于k。二是吞吐率:单位时间内完成的指令数。考虑冒险之后要重新计算实际周期数,这是每份试卷必然出现的计算题类型。我复习时整理了流水线性能计算的完整模板:先算理想周期数n+k-1,再逐个加冒险阻塞周期,分支预测失败还要加冲刷周期,最后除以主频得到总执行时间。只要按这个顺序走,极少出错。
提示:做流水线大题之前,先把题目的前提圈出来——有没有转发?分支在哪个阶段解析?取指和访存共用存储还是分离?这些前提不同,答案完全不同。先把条件写清楚再动笔。
5. 存储层次:Cache与虚拟存储器的设计权衡
5.1 局部性原理:为什么缓存能奏效
存储层次这一章的设计动机是“快、大、便宜”三者不可兼得,所以用层次结构来兼顾。SRAM快但贵,DRAM便宜但慢,磁盘更便宜更慢。缓存的成立依赖于两个局部性:时间局部性(刚访问过的数据很快还会访问)和空间局部性(刚访问过的地址附近的数据很快会被访问)。这一点考试会直接问,答的时候一定把“循环”“数组顺序访问”这两个经典例子带上,这是量化局部性的实例支撑。
理解Cache要从三个基本问题入手:块怎么放置(映射方式)、找不到时替换谁(替换策略)、写的时候怎么处理(写策略)。三个问题对应三个设计维度,任何一道Cache题都逃不出这个框架。复习建议是把Cache画成一张表格,横向是组、纵向是路,每个格子是一行(tag+data+valid位)。画过一次之后,地址字段怎么划分就一目了然了。
5.2 Cache三种映射方式与地址划分
直接映射、全相联、组相联是三种映射方式,差别在于“一个内存块可以放进Cache的哪些位置”。直接映射:每个块只能放一个固定位置,硬件简单但冲突率高。全相联:每个块可以放任意位置,冲突率低但比较器复杂,硬件开销大。组相联:折中方案,Cache分成若干组,每组有n路(n路组相联),块可以放进指定组中的任意一路。
地址划分是必考计算。一个直接映射或者组相联Cache,地址被分成三部分:块偏移(块内字节数取log2)、组索引(组数取log2)、标记(剩余高位)。常见陷阱是块大小是32字节时偏移是5位,组数是64时索引是6位,但题目给出的地址可能是字节地址也可能是字地址,做题前一定看清。另外全相联Cache没有索引字段,只有块偏移和标记。Cache总容量 = 组数 × 路数 × (块大小 + 标记位 + valid位),这个“容量包含标记位”的考点,大题里几乎必考,别漏算。
5.3 替换策略与写策略的取舍
替换策略里,LRU(最近最少使用)是教材重点,它基于时间局部性,替换最久没被访问的行。实现上通常用计数器或“老化位”近似,2路组相联只需1位LRU位,4路需要2位,n路需要log2(n!)位?实际上n路LRU的理想实现比较复杂,教材习题里一般只要求2路或4路的模拟。FIFO、随机替换也会考概念对比,答题要点是LRU命中率最高但硬件最复杂,随机替换虽然命中率不稳定但实现极简单。
写策略分写直达(write-through)和写回(write-back)。写直达是每次写都要写回下一级存储,实现简单但带宽压力大;写回是Cache行被替换时才写回,带宽高效但需要脏位(dirty bit)标识该行是否被修改过。还有一个组合维度是写不命中时——是写分配(将块调入Cache再写)还是写不分配(直接写下一级,不调入)。考试喜欢考“某Cache是写回+写分配,访问序列给出命中/缺失情况,计算最后的Cache内容”。这类题要一步步模拟,注意写回模式下缺失时如果旧行是脏的,必须先写回旧块再调入新块。
5.4 Cache性能计算:缺失率、平均访问时间
Cache性能的核心指标是平均访存时间AMAT = 命中时间 + 缺失率 × 缺失代价。多级Cache则要逐级展开。一个典型的二级Cache计算:L1命中1周期,L1缺失率5%,L2命中10周期,L2缺失率20%,L2缺失后主存代价100周期。AMAT = 1 + 5% × (10 + 20% × 100) = 1 + 0.05 × 30 = 2.5周期。注意括号里的20%是L2的缺失率,和L1缺失率是两个不同层次的事件概率,不能直接相乘完事,先算L2的平均惩罚再乘L1缺失率才正确。
缺失的三种类型(3C)也是高频概念:强制缺失(首次访问必然缺失)、容量缺失(Cache装不下工作集)、冲突缺失(映射到同一组造成的缺失)。增大Cache容量可以减少容量缺失;提高相联度可以减少冲突缺失;强制缺失无法通过Cache设计消除,只能通过预取等手段缓解。这个分类在简答题里经常出现,记忆方法是从“为什么缺失”这个原因出发,而不是死背定义。
5.5 虚拟存储器与TLB的原理
虚拟存储器的本质是把主存当作磁盘的Cache,它在体系结构课程里的考点集中在页式管理、页表和TLB。虚拟地址分成虚拟页号和页内偏移,通过页表翻译成物理地址。考试常画两级页表和倒排页表的结构图,但更常考的是“缺页处理流程”:缺页异常发生时,CPU陷入操作系统,由OS从磁盘调入页面,如果内存满了还要选一个页换出,这就是页面替换算法(FIFO、LRU、时钟算法等)的考点。
TLB是页表的缓存,和Cache是两回事:TLB缓存的是“虚拟页号到物理页号的映射”,Cache缓存的是“内存数据”。处理器访存时要先查TLB,再查Cache,这个顺序关系是很多同学的盲点。还有一种题目会把TLB、访存缺失、缺页组合在一起,让你判断某个访存操作需要访问几次存储器。做这种题,我建议画一个两级流程:先标TLB命中与否,再标Cache命中与否,最后把缺页这个最慢路径单独拎出来。顺序画完就不会漏。
6. 中断、I/O与总线机制
6.1 中断的完整处理流程
中断和异常是操作系统和体系结构的接口。考试一般要求说清楚中断响应的大致流程:CPU检测到中断请求信号,在当前指令执行完后响应;保存PC等现场信息;根据中断向量找到中断服务程序入口;执行中断服务程序;最后恢复现场返回被中断的程序。关键点是“当前指令执行完才响应”和“保存现场”,这两个是判断你是否真正理解中断机制的试金石。
中断和异常的差别也要会辨析。异常(exception)是CPU内部产生的,比如缺页、溢出、非法指令;中断(interrupt)是外部设备发起的输入输出事件。在MIPS体系结构里,两者统一用异常向量处理,但产生来源不同、处理时机的确定性也不同。这个对比题几乎每届都考,答题时要从“来源”“同步/异步”“产生时刻是否确定”三个角度展开。
6.2 DMA与程序控制I/O的对比
I/O这块考试的重点是比较三种I/O方式:程序查询(轮询)、中断驱动、DMA。程序查询是CPU不断检测设备状态寄存器,效率最低;中断驱动是设备完成传输后发中断通知CPU,CPU不用干等,但每次传输还是以字为单位,中断频繁;DMA(直接存储器访问)由DMA控制器接管数据搬运,只在整块数据传完后发一次中断,CPU可以在传输期间做其他事。
概念题会问“为什么DMA能提高CPU利用率”,答题点有三个:数据搬运由DMA控制器完成而不占CPU寄存器;中断频率低(块传输完一次中断);CPU可以与其他程序并行运行。计算题则经常给一个外设的传输速率,让你算在程序查询方式下CPU被消耗的时间占比,以及改成DMA后节省了多少CPU时间。这类题的关键是单位换算:把字节、秒、Hz统一成同一套单位再算。
7. 多处理器与并行体系结构
7.1 并行计算分类与一致性问题的来源
多处理器章节的切入点一般是Flynn分类:SISD(单指令单数据,传统单核)、SIMD(单指令多数据,如向量处理器和GPU)、MIMD(多指令多数据,多核处理器)。MIMD又分为共享内存和消息传递两种模型。共享内存模型里,多个处理器共享同一地址空间,彼此通过读写共享变量通信,但这就带来了缓存一致性问题。
为什么需要缓存一致性?因为每个处理器都有自己的私有Cache,同一个内存地址的数据可能被多个处理器各缓存一份。如果处理器A改了它缓存里的数据,处理器B不知道,仍然用它缓存里的旧值,程序就跑错了。这个问题不是“谁对谁错”能解决的,而是硬件必须保证所有处理器对同一地址的访问最终看到一致的值。一致性协议就是为此设计的。
7.2 缓存一致性协议MESI
MESI协议是考试最爱考的缓存一致性协议,它以缓存行的四种状态命名:M(Modified,已修改)、E(Exclusive,独占)、S(Shared,共享)、I(Invalid,无效)。每个缓存行要么是干净的独占(只有我有且与内存一致)、要么是干净的共享(多个处理器有且与内存一致)、要么是脏的独占(我改过且还没写回,内存的值已过期)、要么是无效的(这个副本不能用)。转换规则记住三条核心动作:本地读、本地写、监听其他处理器的读/写请求(总线嗅探)。
做题时MESI的模拟是流程化的:监听到其他核读某个地址时,如果你持有M态的行,必须先把数据写回内存或直接转交给请求方;监听到其他核写某个地址时,你持有的S态或E态行都要变成I态,因为别人改了就跟你无关了。我复习时把MESI状态转换画成四状态图贴在书桌上,每天默写一遍,考试时这类题基本能全对。还有一个容易混淆的概念是“一致性协议”和“一致性模型”的区别:协议解决的是“什么时候传播更新”,模型解决的是“读操作能读到什么旧值”,后者更偏理论。
7.3 存储一致性模型
存储一致性模型规定多处理器系统里读写操作在不同处理器上的可见顺序。顺序一致性(sequential consistency)是最直观的模型:所有处理器的访存操作看起来像按某个全局顺序执行,且每个处理器的操作顺序保持不变。但顺序一致性限制了硬件优化空间,所以实际系统往往放松约束,比如处理器一致性、弱一致性等。考试一般只要求掌握顺序一致性的定义,并判断一段多线程程序在某个模型下是否可能出现某种结果。
这部分在山大课程里不属于必考大题的权重,但简答题出现过。答题记住一点就行:顺序一致性要求“全局顺序存在”,而放松模型允许某些乱序,代价是程序员要自己用同步机制(如锁、内存屏障)来保证正确性。这也是“硬件简化和软件复杂度”之间权衡的经典例子,和前面RISC的设计哲学一个道理。
8. 期末复习:题型归纳与备考心得
8.1 计算题的四种常见套路
翻完近五年的期末题,计算题基本集中在四个固定类型上。第一是性能计算:CPU时间、CPI、Amdahl定律,通常两个小题连在一起考,先算混合CPI再算加速比。第二是流水线:给几条指令让你画带转发和阻塞的时序图,或者算总周期数,这一题分值最高,也是失分重灾区,务必把数据通路和控制信号的细节背熟。第三是Cache:给容量、块大小、映射方式、访问序列,让你算命中率、平均访存时间、最后Cache内容,3C缺失类型也常混在里面考。第四是MESI:给一个两处理器并发访问序列,填状态转换表。
针对这四种题型,我的复习方法是各找三道真题,第一道看答案做、第二道合上答案做、第三道限时做。三遍之后你会发现套路其实很有限,每种题型的“第一步干什么、第二步干什么”都是固定的。比如Cache题永远先确定块偏移位数,再确定索引字段,最后列访问序列模拟,这种流程化操作比临场推导可靠得多。
8.2 概念题的高频考点
概念题也不需要死记硬背,重点抓几组对比关系。体系结构和微架构的区别、RISC和CISC的区别、中断和异常的区别、写直达和写回的区别、LRU和FIFO的区别、顺序一致性和放松模型的区别,这六组对比是出题人最喜欢的素材。每个对比都有自己的答题框架:定义分别是什么、关键差异在哪、各自优缺点、典型应用场景。用这个框架去答,哪怕记不全课本原话也能拿大部分分数。
还有一个容易被忽略的点是“量化对比”,比如问“为什么提高相联度能降低缺失率但代价高”,除了写定义,最好带上数字:4路组相联和直接映射在同一个程序上缺失率可能从5%降到3%,但需要4路比较器并行比较标记,硬件功耗和面积显著增加。这种“定性+定量”的答案,阅卷时会明显高出空泛回答一档。
8.3 复习节奏与个人建议
我的建议是三轮复习。第一轮跟着教材章节过知识点,每章结束合上书用一页纸默写该章的核心概念和公式,默不出来就回去翻,这是检验“以为自己会了”的最好办法。第二轮主攻计算题,把课本习题和配套习题指导里的题目全部刷一遍,错题标出来,分析是公式错还是流程错。第三轮做模拟卷,严格限时两小时,重点练“拿到一道题能不能快速识别题型并选择正确公式”。
最后再说一个我自己踩过的坑:不要只背公式不理解适用条件。比如Amdahl定律里的F是时间占比不是指令数占比,Cache缺失率在不同块大小下不能直接比较,流水线加速比的前提是各级延迟均衡。这些“使用边界”恰恰是考点所在,也是这门课真正想培养的计算思维——任何优化都是有代价的,任何指标都是有前提的,理解了这一点,体系结构的核心精神才算真正学到手。