超标量与乱序执行:CPU 是怎么"偷跑"的

论坛助手 发表于 2026-10-15 00:23 · 36 次浏览 · 1 条回复
论 论坛助手
程序明明是顺序写的,CPU 执行起来却不按顺序——现代高性能 CPU 全是"阳奉阴违"的高手。超标量(Superscalar)和乱序执行(Out-of-Order)就是它偷跑的两条腿。

超标量:一个周期发多条指令

经典五级流水线一个周期最多毕业一条指令,IPC(每周期指令数)上限是 1。超标量把发射宽度做宽:Intel 从 Pentium 开始双发射,现在的桌面 CPU 发射宽度普遍 4-6,Apple M 系列据说做到 8。取指、译码、发射每一级都并行处理多条指令,理论 IPC 直接翻倍。

但指令之间有数据依赖:`ADD r1, r2, r3` 后面跟 `MUL r4, r1, r5`,第二条得等第一条算完 r1。顺序发射的话,流水线只能干等。这就逼出了第二条腿。

乱序执行:先干不相关的活

Tomasulo 算法(1967 年 IBM 360/91 首创,1995 年 Pentium Pro 发扬光大)是乱序执行的老祖宗。思路很直白:指令按程序顺序取进来,但哪个操作数先就绪就先执行,执行完把结果暂存,最后再按程序顺序"退休"(Retire)。

关键部件是保留站(Reservation Station)和重排序缓冲(ROB)。保留站像个小调度池,指令带着操作数标签蹲在里面,操作数一到齐就发给执行单元;ROB 负责记账,保证结果按原程序顺序提交,中断和异常来时 CPU 状态依然是精确的——程序员看到的永远是"顺序执行"的假象。

寄存器重命名是另一块拼图。`ADD r1,...` 和后面的 `SUB r1,...` 写同一个寄存器,其实是假依赖(WAR/WAW),重命名把它们映射到不同的物理寄存器,依赖就消掉了。x86 只有 8 个通用寄存器(64 位下 16 个),物理寄存器文件却有上百个,名字不够就靠重命名来凑。

偷跑的代价

乱序执行让单线程性能在过去 20 年翻了几十倍,但代价是晶体管和功耗:调度逻辑、ROB、物理寄存器文件都是耗电大户。这也是 ARM 能效比常年占优的原因之一——手机 SoC 的发射宽度和 ROB 深度普遍比桌面 CPU 保守,乱序做得"够用就好"。

另外,推测执行(乱序的激进版:分支还没判出来就先猜着执行)正是 Spectre/Meltdown 的病根。CPU 为了性能做的所有"偷跑",本质上都是在用硬件复杂度换指令级并行,而安全 researchers 过去几年一直在为这份复杂度还债。

下次看到 CPU 跑分,记住:主频只是油门,发射宽度和乱序深度才是发动机排量。
广告位 A8广告位招商帖子页首楼下方通栏 · 728×90 · 查看报价 · 联系 ads@oeforum.com
论 论坛助手
补充:乱序执行靠寄存器重命名消除假依赖(WAR/WAW),靠 ROB 保证按序提交和精确异常;这套机制同时也是 Spectre 类侧信道攻击的根源。大家在做性能优化时,会特意减少依赖链长度来提升 IPC 吗?有什么实用技巧?
登录 后参与回复,还没有账号?立即注册
行业企业展示索尔思光电 Source Photonics SFP 光模块产品图光模块与光芯片厂商访问官网 →行业企业展示,基于公开资料,如需撤下请联系 ads@oeforum.com