指令流水线每次软考中级软件设计师必出一到两道选择题,分值不高但极其稳定。很多人靠背公式蒙答案,蒙对了不知所以然,蒙错了也找不出原因。这篇文章从计算机组成原理底层把流水线的本质掰开揉碎,再配合历年真题的命题规律,读完看到流水线题三秒出答案。
先给一个精确的定义。指令流水线是 CPU 在程序执行时,将每条指令的处理过程拆分为若干个功能独立的子阶段,各子阶段由不同的硬件部件分别完成,从而使多条指令的不同子阶段在时间上重叠执行的一种准并行处理技术。请注意"准并行"三个字:流水线不是真正的并行——任何一个时刻,CPU 内部只有一条指令在执行,但不同指令的不同阶段可以同时进行,就像工厂流水线上不同工位同时加工不同的产品。
典型五级流水线把一条指令的执行分为五个阶段。取指阶段从内存读出指令送入指令寄存器,程序计数器自增指向下一条指令。译码阶段解析操作码和寻址方式,从寄存器堆读取源操作数。执行阶段由算术逻辑单元完成运算或计算访存有效地址。访存阶段通过数据总线读写内存,仅加载和存储指令真正用到。写回阶段将运算结果写入目标寄存器。五个阶段各由独立硬件电路负责,可以同时工作在不同的指令上。
每个阶段完成工作所需时间称为"流水段延迟",耗时最长的那个阶段决定了流水线的节奏,被定义为"流水线周期"。核心规则:流水线每个时钟周期必须等最慢的阶段做完,同一时钟节拍下所有阶段统一推进。如果取指四纳秒、译码两纳秒、执行三纳秒,流水线周期就是四纳秒,译码和执行阶段每周期都会有空闲等待。
软考中考流水线性能计算,本质上只考两条公式。第一条是"完成 N 条指令的总时间",第二条是"吞吐率和加速比"。搞懂这两条,考试不会翻车。
先说总时间。设流水线有 K 个阶段,每个阶段耗时分别为 T1、T2 到 TK,其中最大值即为流水线周期,记作 Tmax。第一条指令必须流水线"灌满",即依次经过全部 K 个阶段,耗时等于各阶段时间之和:T1加T2加一直加到TK。从第二条指令开始,每个流水线周期就能吐出一条完成的指令,因为流水线已经满载运转。因此执行 N 条指令的总时间为:第一条指令各阶段时间之和加上括号 N 减一括号乘以流水线周期。
举个例子:某流水线取指四纳秒、译码两纳秒、执行三纳秒,执行一百条指令。第一条指令四加二加三等于九纳秒,流水线周期取最大值为四纳秒,剩余九十九条指令每条四纳秒,总时间九加九十九乘四等于四百零五纳秒。这道题正是二零二一年下半年软件设计师真题第十五题,答案四百零五。
这道题的常见错误是把九加三乘九十九算成三百零六,或者直接用流水线周期乘一百得到四百。错误根源在于混淆了"第一条指令各阶段之和"与"流水线周期"这两个概念。第一条指令流水线还没灌满,必须走完所有阶段才能出结果;而后续指令由于流水线已满载,每隔一个周期就能吐出一条。
接下来是吞吐率。吞吐率定义为单位时间内流水线完成的指令数量,即指令数除以总时间:N 除以总时间。当 N 趋向于无穷大时,最大吞吐率趋近于流水线周期的倒数。二零一七年下半年系统架构设计师真题第一问就是考这个:五级流水线各段时间为两Δt、一Δt、三Δt、一Δt、两Δt,瓶颈段为取操作数的三Δt,最大吞吐率等于三分之一个每Δt。注意吞吐率的倒数就是流水线周期,这本身是一个物理量纲关系——瓶颈段决定了流水线能跑多快。
加速比则是同一批指令在非流水线方式下的总时间除以流水线方式下的总时间。非流水线方式每条指令串行执行,总时间为 N 乘以各阶段时间之和。二零一七年系统架构设计师真题第二问:十条指令顺序执行需九十Δt,流水线方式第一条九Δt加九乘三Δt得三十六Δt,加速比九十比三十六等于五比二,即二点五倍。
流水线不是完美无缺的技术,它有三种"冒险",软考虽然不要求你写代码解决冒险,但理解这三种冒险的成因和解决方法,是区分"会做题"和"真理解"的分水岭。
结构冒险发生在多条指令同时争用同一硬件资源时。五级流水线中取指需访问指令存储器、访存需访问数据存储器,若指令和数据共用一条总线和一个存储器——即经典的冯·诺依曼瓶颈——取指和访存就无法在同一周期进行,流水线必然停顿。解决方案是哈佛架构,将指令和数据存储器物理分离,各自走独立总线互不干扰。现代 CPU 一级缓存也分指令缓存和数据缓存,道理相同。
数据冒险比结构冒险更棘手。当后一条指令的源操作数是前一条指令尚未写回的结果时,流水线出现"读后写"依赖。举例:指令一计算R1加R2写入R3,指令二紧跟要用R3加R4。五级流水线中指令一的写回在第五周期才完成,而指令二的译码在第三周期就要读R3——此时R3未写入,指令二读到旧值,结果错误。解决思路有两种:一是硬件"旁路转发",将执行阶段刚算出的结果通过额外数据通路直接送到下一条指令的执行输入端,绕过写回再读出的延迟;二是编译器指令调度,在两条相关指令之间插入无关指令,给前一条指令留出写回窗口。
控制冒险由分支指令引发。条件跳转指令在译码或执行阶段才知是否跳转、跳向何处,而取指阶段已贪婪地取了下一条指令——分支一旦发生,已取指令必须作废,流水线产生"气泡"。解决手段是分支预测:静态预测永远假设分支不发生,简单但错误率高;动态预测根据历史跳转记录建立分支目标缓冲区,准确率可达百分之九十以上。软考对控制冒险的
本篇完!