指令流水线技术
本章为进阶内容,零基础读者可以跳过,不影响后续阅读。
复习
- 第三十八章:了解了 CPU 按“取指 → 译码 → 执行 → 写回“的循环工作
TL;DR
- 流水线让多条指令的不同阶段重叠执行,从而成倍提高吞吐率
- 流水线会遇到数据冒险、控制冒险、结构冒险,需要转发、停顿、预测等手段处理
- 超标量、乱序执行等是流水线的进一步发展
正文
从洗衣房说起
假设洗一桶衣服要经过“洗 → 烘 → 叠“三步。如果一个人从头做到尾,一桶接一桶地干,那他大部分时间都在等机器,很浪费。
但如果有三个人流水作业:一个负责洗,一个负责烘,一个负责叠,那么第一桶在烘的时候,第二桶已经在洗了。虽然单桶的总时间没变,但每小时完成的桶数(吞吐率)大大提高了。
流水线(Pipeline)就是这个思路用到 CPU 上。
五级流水线
把指令执行拆成五个阶段:
- F(Fetch):取指令
- D(Decode):译码
- E(Execute):执行
- M(Memory):访存
- W(Write-back):写回
不流水时,一条指令占满五个阶段,下一条只能干等。流水之后,每一拍都有五条指令分别处于五个阶段:
指令1: F D E M W
指令2: F D E M W
指令3: F D E M W
指令4: F D E M W
流水线填满后,每个时钟周期就能完成一条指令。前面思考题里那个“1000 条指令只要约 1003 个周期“的答案,就是这么来的。
流水线的冒险
现实中没这么理想,会出现冒险(Hazard),也就是让流水线卡壳的冲突。主要有三类:
- 数据冒险:后一条指令要用前一条还没算出来的结果。
- 例:
ADD R1,R2,R3后面紧跟SUB R4,R1,R5,R1 还没写好就要用 - 解决:转发(把还没写回的结果直接送过去)、必要时停顿(插几个空拍)
- 例:
- 控制冒险:遇到分支跳转,不知道下一条该取哪里。
- 解决:分支预测(猜一把,猜错再倒回来)、延迟槽等
- 结构冒险:多条指令抢同一个硬件资源(比如同时要访问存储器)。
- 解决:把指令缓存和数据缓存分开、增加功能部件
更进一步
在流水线的基础上,工程师们还发明了:
- 超标量:一条流水线不够,就并排开好几条,一拍发射多条指令
- 乱序执行:谁的数据先准备好谁先算,不必死守程序顺序,最后再按顺序提交结果
- 寄存器重命名:消除指令间不必要的数据依赖,让并行更充分
这些技术让现代 CPU 能用几百甚至上千条“在途指令“来填满流水线。它们已经属于计算机体系结构的高阶内容,这里点到为止,知道有这么回事即可。
思考题
流水线把速度提高了,代价是什么?为什么流水线级数不是越多越好?
小结
知识点
- 流水线的基本思想与五级流水线
- 数据冒险、控制冒险、结构冒险
- 转发、停顿、分支预测
- 超标量与乱序执行
参考资料
- Wikipedia(zh):指令流水线:流水线的基本概念
- Wikipedia(zh):超标量处理器:超标量技术
- Wikipedia(zh):乱序执行:乱序执行原理
思考题答案(仅供参考)
代价是复杂度:流水线级数越多,每一级能分到的活儿就越少,而“填满“和“排空“流水线的固定开销、冒险带来的停顿、时钟同步的代价都会上升。而且级数越多,一旦遇到分支预测失败,需要倒回去的指令也越多。所以级数要取一个平衡点,不是越多越快。
协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
封面图
设计师 | 南国微雪