CPU 微架构·让 CPU 变快的十二个发明
同样是 5 GHz,今天一颗 CPU 核心比 2005 年的快好几倍。差别不在“跑得多快”,而在“每一拍干了多少活”。这一页逐个讲清十二个发明:流水线、超标量、乱序执行、分支预测、推测执行、缓存、SIMD、超线程、多核、集成内存控制器、睿频和 µop 缓存。每一个都讲它为什么诞生、解决了什么、有什么毛病、现在怎么样。
性能 = 频率 × 每拍干的活
频率提不动以后,几乎所有的进步都来自“每拍多干点”和“少等一会”。
在 CPU 入门 里我们讲过:CPU 不停地重复“取指令、译码、执行”。它跟着一个节拍器走,这个节拍器叫时钟,每秒跳 50 亿下就是 5 GHz。一拍只有 0.2 纳秒,光在这段时间里只能走 6 厘米。
一个程序跑多快,可以拆成一个简单的乘法:
微架构(microarchitecture)就是“CPU 核心内部怎么设计”。同一套 x86 指令集,Intel 和 AMD 可以用完全不同的微架构去实现,就像同一份菜谱,不同饭店的厨房布局完全不同。1990 年代,频率从几十 MHz 涨到 1 GHz 以上,几乎是白送的;2005 年前后频率撞墙(原因见 晶体管),此后的提升主要来自提高 IPC 和增加核心数。下图是一个现代核心的“地图”,十二个发明各住在哪里。
- 1流水线:把一条指令拆成几步,像流水线一样接力。
- 2超标量:多个执行单元,一拍发出好几条指令。
- 3乱序执行:调度器挑“材料已备齐”的指令先做。
- 4分支预测:遇到岔路先猜方向,不停下来等。
- 5推测执行:按猜的方向先做,结果暂存在 ROB 里。
- 6缓存分级:L1、L2、L3,把常用数据放在手边。
- 7SIMD:一条指令同时算一排数。
- 8超线程:一个核心同时跑两个线程,填满空闲。
- 9多核:一颗芯片里放很多个核心。
- 10集成内存控制器:管内存的电路搬进 CPU。
- 11睿频:温度和功耗允许时自动超频。
- 12µop 缓存:记住译好的指令,下次免译。
洗衣房里的大智慧
一条指令要走好几步。与其等它全部走完再开始下一条,不如像接力一样,每一步都同时有人在忙。
为什么诞生。早期 CPU 一次只处理一条指令:取指、译码、执行、写回全部做完,才开始下一条。问题是每一步只用到 CPU 的一部分电路,其他部分都在发呆。1960 年代 IBM 的 Stretch(1961)和 CDC 6600 等大型机先用上了“重叠执行”;1980 年代的 RISC 芯片(如 MIPS)把经典的五级流水线做成了教科书。x86 上,1989 年的 i486 第一次有了完整的五级流水线,1993 年的 Pentium 把它发扬光大。
按“下一拍”开始。
它解决了什么。五级流水线理想情况下把吞吐量提高到接近 5 倍。更妙的是,每一级要做的事变少了,所以每一拍可以更短,频率也能提高。这就是 1990 年代主频狂飙的秘诀之一。
它的缺陷。流水线最怕“断流”。后一条指令要用前一条的结果(数据依赖),或者遇到岔路不知道往哪走(分支),流水线就得停下来等,这叫气泡。流水线越长,断流的代价越大。Pentium 4 把流水线拉到 20 级、后来 31 级,想冲 10 GHz,结果功耗和猜错代价双双失控,详见 走进死胡同的路线。
现状。所有现代 CPU 都是流水线的。今天的高性能核心大约 14 到 20 级,是“频率”和“断流代价”之间的折中。后面讲的几个发明(分支预测、乱序执行),很大程度上就是为了让长流水线别断流。
一条流水线不够,就开四条
流水线让“每拍完成一条”,超标量想要“每拍完成好几条”。
为什么诞生。流水线做到极致,也只能每拍出一条指令(IPC = 1)。要再快,就得在同一拍里同时做好几条:多放几个加法器、几套译码器。这种设计叫超标量(superscalar,“超过标量”的意思,标量就是一次处理一个)。1964 年的 CDC 6600 已经有 10 个独立的功能单元;1990 年 IBM 的 RS/6000 让这个词流行起来。x86 上,1993 年的 Pentium 有 U、V 两条整数流水线,是第一颗超标量 x86。
它解决了什么。突破了 IPC = 1 的上限。今天的高端核心,如 AMD Zen 5 和 Intel Lion Cove,每拍能分派约 8 个操作,苹果 M 系列的大核更宽。
它的缺陷。越宽越难填满。原因有三:指令之间有依赖;x86 指令长短不一,一拍译出很多条非常难(见发明 12);每多一条通道,检查“谁依赖谁”的电路就要成倍增加,面积和功耗上升。所以只靠“加宽”不够,还得配上下一个发明:乱序执行,帮它找到可以同时做的指令。
现状。所有桌面、服务器、手机大核都是超标量。这场“加宽竞赛”还在继续,但每加宽一次换来的提升越来越少。
谁的材料先齐,谁先下锅
程序写的是一个顺序,CPU 真正干活时会悄悄换个顺序,最后再按原顺序交卷。
为什么诞生。想象一个厨师按菜单顺序做菜:第一道菜要等送货员送来鱼,他就站着等 20 分钟,后面三道蔬菜也不做。这显然很傻。CPU 里最常见的“等鱼”是等内存:读一次内存要上百个时钟拍。1967 年 IBM 的 Robert Tomasulo 为 System/360 Model 91 设计了一套算法,让后面不相关的指令先做,这就是乱序执行(out-of-order execution)。x86 上,Intel 1995 年的 Pentium Pro(P6 架构)第一次把它带进来,AMD 随后在 K5、K6(来自收购的 NexGen)上也跟进。
它是怎么做到“乱中有序”的
- 重命名给每条指令的结果分配一个临时“格子”,避免假冲突。
- 进候场区指令在调度器里等材料(操作数)齐。
- 谁齐谁先做调度器每拍挑出已经齐了的指令,发给执行单元。
- 按序交卷结果先放进重排序缓冲(ROB),再按程序原顺序正式生效。
它解决了什么。把等内存、等除法这些“慢动作”的时间用来干别的活,是 IPC 提高最大的功臣之一。Pentium Pro 的 ROB 能放 40 条指令;今天的大核能同时“在飞”约 500 条(Zen 5 约 448 条,Intel Golden Cove 约 512 条)。
它的缺陷。非常耗电、耗面积。重命名表、调度器、ROB 这些“记账”电路,常常比真正做加法的电路还大。所以低功耗的小核(如早期 Atom)曾经故意不用乱序执行。另外,它和下面的推测执行结合后,埋下了 2018 年安全漏洞的伏笔。
现状。所有 PC 和服务器 CPU 的大核都是乱序的;Intel 从 2013 年的 Silvermont 起,连 Atom 小核也改成了乱序。
遇到岔路,先猜一个
程序里大约每五六条指令就有一个“如果……就……”。流水线不能每次都停下来等答案。
为什么诞生。“如果分数大于等于 60,就打印及格,否则打印不及格”,这种语句在机器里叫分支。问题是:分支条件要到“执行”那一步才算出来,可流水线的“取指”早在好几拍之前就得决定下一条从哪取。停下来等?一条 15 级的流水线每遇到一个分支就要白等十几拍,而分支又这么多。所以 CPU 必须先猜。
最早的办法是“静态猜”,比如“往回跳的总是猜跳”(循环大多如此)。1981 年 James Smith 提出用一个 2 位计数器记住每个分支最近的表现;1991 年 Yeh 与 Patt 提出“两级预测”,把最近一串分支的走向也考虑进去。x86 上,1993 年的 Pentium 带有分支目标缓冲(BTB),Pentium Pro 用上了两级预测。
它解决了什么。现代分支预测器的准确率在常见程序里通常超过 95%,有的测试里接近 99%。AMD 从 2017 年的 Zen 起公开使用基于“感知机”(一种最简单的神经网络,2001 年 Jiménez 与 Lin 提出)的预测器,后来又加上 TAGE 类预测器(2006 年 André Seznec 提出)。预测器越准,流水线就可以越长、越宽。
它的缺陷。猜错一次,就要扔掉已经进入流水线的十几到上百条指令,浪费时间也浪费电。对于真正随机的数据(比如加密、压缩),再聪明的预测器也只能靠运气。预测器本身也越来越大,要占不少面积。
现状。它是 CPU 设计公司最核心的“秘方”之一,细节很少公开。每一代新核心几乎都会宣传“分支预测更准、容量更大”。
先做了再说,以及 2018 年的那次翻车
猜了方向还不够,CPU 会沿着猜的方向一路往下真的去做,猜错了再撤销。
为什么诞生。分支预测只是猜“下一条从哪取”。如果取进来的指令不去执行,乱序执行就没活可干。于是 CPU 干脆沿着猜的路径真的执行下去,把结果先暂存在 ROB 里,等分支结果出来:猜对了就正式生效,猜错了就整个丢掉。这叫推测执行(speculative execution)。它和乱序执行是一对搭档,1995 年 Pentium Pro 起成为 x86 的标配。
它解决了什么。让乱序引擎的几百个格子能一直装满。没有它,乱序执行最多只能看到下一个分支之前的几条指令。
缺陷:撤销不干净
设计者原本以为:猜错的结果反正都丢了,程序看不到,就等于没发生过。2018 年 1 月 3 日,Google Project Zero 的 Jann Horn 和几个学术团队(包括格拉茨工业大学、Paul Kocher 等)同时公布了两类漏洞:Meltdown(熔断)和 Spectre(幽灵)。它们证明:寄存器里的结果虽然撤销了,但推测执行时顺手读进缓存的数据不会撤销。攻击者测量“读哪一格特别快”,就能把本不该看到的秘密一点一点“读”出来。这种靠测时间偷信息的方法叫侧信道攻击。
后果。操作系统紧急打补丁(例如把内核内存和用户程序彻底隔开的 KPTI,以及编译器里的 retpoline 技巧)。对频繁调用系统功能的程序,如数据库和存储服务,早期补丁带来的性能损失据报道在个位数到 30% 不等。之后几年又陆续冒出同类漏洞:Foreshadow(2018)、MDS / ZombieLoad(2019)、Zenbleed(2023,AMD Zen 2)、Downfall(2023,Intel)、Inception(2023,AMD)。
现状与未来。推测执行没法放弃,放弃了性能会倒退十几年。厂商的办法是在硬件里补洞:Intel 从 2018 年底到 2019 年的新芯片起,在硬件层面修复了 Meltdown,并为各种变体加了“隔离”开关。今天“安全”已经和“性能”“功耗”并列成为微架构设计的第三个目标,每次发布新核心都要说明对这类攻击的防护。
内存墙:CPU 等数据,比算数据还久
CPU 越来越快,内存只是越来越大。两者的速度差距,靠一层层的缓存来填。
为什么诞生。CPU 要处理的数据放在内存(DRAM,就是电脑里的内存条)里。1980 年以后,CPU 每年快约 50%,内存的反应速度每年只快几个百分点。到 1990 年代,CPU 等一次内存要几十上百拍。1995 年 Wulf 和 McKee 写了一篇论文,给它起名内存墙(memory wall)。
解决办法是缓存(cache):在 CPU 旁边放一小块又快又贵的存储(SRAM,用 6 个晶体管存 1 位),把最近用过的数据和它旁边的数据放在里面。这能行,是因为程序有“局部性”:刚用过的数据,很可能马上再用;用了第 100 号,很可能接着用第 101 号。1968 年 IBM System/360 Model 85 是第一台商用带缓存的计算机。x86 上,1989 年 i486 把 8 KB 缓存做进芯片;1995 年 Pentium Pro 把 L2 放进同一个封装;1999 年 Pentium III(Coppermine)把 L2 做进芯片;2007 年 AMD Phenom、2008 年 Intel Nehalem 给多个核心加了共享的 L3。
每 1000 次读数据,约 3 次要一路跑到内存。
假设 L1 约 1 ns、L2 约 4 ns、L3 约 12 ns、内存约 90 ns。进度条长度表示平均等待占“直接读内存”的比例。
它解决了什么。常见程序里,L1 的命中率通常在 90% 以上。缓存让 CPU 大多数时候感觉不到内存有多慢。今天一颗 CPU 芯片上,缓存往往占去三分之一甚至一半的面积。
它的缺陷。贵、占地方,而且 SRAM 在新工艺下几乎缩不动了(见 晶体管)。缓存越大越慢,所以只能分层。多个核心共享数据时,还要有一套“一致性”机制保证大家看到的数据一样,又增加了复杂度。缓存也是前面侧信道攻击的“作案工具”。
现状与未来。缓存越来越大,开始往“上下”长:AMD 的 3D V-Cache 用混合键合在芯片上叠了一层 64 MB 的 L3(2022 年 5800X3D,详见 AMD 路线 和 混合键合),游戏性能明显提升。Intel 也计划在后续产品里用堆叠缓存。内存本身也在往 CPU 靠:Lunar Lake 把内存放进封装,服务器和 AI 芯片用 HBM。
一条指令,同时算一排数
处理图片、声音、视频时,同样的运算要对成千上万个数做一遍。SIMD 让 CPU 一次做一排。
为什么诞生。1990 年代中期,PC 开始播放 MP3、VCD 和 3D 游戏。这些任务的特点是:同一个操作(比如“亮度加 10”)要对几百万个像素各做一遍。普通指令一次只能算一对数。SIMD(单指令多数据,Single Instruction Multiple Data)的想法是:把一个很宽的寄存器切成好几格,一条指令同时算所有格。
一路加宽的历史。1997 年 Pentium MMX 带来 MMX(64 位,只能算整数,还和 x87 浮点单元共用寄存器,两者不能同时用)。1999 年 Pentium III 的 SSE 加了独立的 128 位寄存器,能算浮点;2000 年 SSE2 能算双精度。2011 年 Sandy Bridge 的 AVX 把宽度翻到 256 位,2013 年 Haswell 的 AVX2 补上整数运算和“乘加”指令。2016 年 Xeon Phi、2017 年 Skylake 服务器版引入 512 位的 AVX-512。
它解决了什么。视频编解码、图片处理、科学计算、加密、压缩、数据库,甚至字符串搜索,都靠 SIMD 提速好几倍。在 CPU 上跑小型 AI 模型时,它也是主力。
它的缺陷。第一,碎片化:AVX-512 有十几个子集,不同芯片支持的不一样,软件很难写。第二,又热又降频:早期 Intel 服务器芯片跑重度 AVX-512 时会主动降频,有时反而拖慢别的程序。第三,大小核不匹配:2021 年 Alder Lake 的能效核(E 核)不支持 AVX-512,Intel 只好在消费级芯片上把它关掉,2022 年后出厂的芯片干脆在硬件上屏蔽。讽刺的是,AMD 从 2022 年 Zen 4 起反而支持了 AVX-512,Zen 5 在桌面和服务器上做成了完整的 512 位数据通路。
现状与未来。2023 年 Intel 发布 AVX10 规范,想把这一团乱麻统一起来:一个版本号说清支持什么,大核小核都支持同一套指令。2025 年 Intel 修订规范,让 AVX10.2 在所有核心上都支持 512 位。据报道,Intel 计划在 2026 年底的 Nova Lake 起让消费级芯片重新支持 512 位向量。另一方面,大量 AI 运算已经转移到 GPU 和 NPU(见 AI 芯片),CPU 上的 SIMD 更多承担“通用的小块并行”工作。
一个厨房,两个厨师轮流用灶台
一个核心的执行单元大部分时间吃不饱。让第二个程序进来,把空档填上。
为什么诞生。先认识一个词:线程,就是一串要按顺序执行的指令,可以理解为“一个任务”。前面讲过,超标量核心有好几个执行通道,但一个线程常常凑不出那么多可以同时做的指令,尤其在等内存的时候,通道大片空着。1995 年前后,华盛顿大学的 Dean Tullsen、Susan Eggers、Henry Levy 等人提出同时多线程(SMT):让一个核心同时装两个线程的状态,执行单元谁有活就给谁。Intel 在 2002 年把它用在 Xeon 和 Pentium 4(3.06 GHz)上,起名超线程(Hyper-Threading)。AMD 直到 2017 年的 Zen 才用上 SMT。
它解决了什么。只多花约 5% 的芯片面积,就能在多任务、服务器负载下多出约 15%–30% 的吞吐量。操作系统里一个物理核心显示成两个“逻辑处理器”,就是这个原因。
它的缺陷。两个线程共用缓存和执行单元,彼此能“听到”对方的动静。2018 年的 PortSmash 等研究证明,可以借此偷取同一核心上另一个线程的加密密钥,OpenBSD 当年因此默认关闭了超线程。对游戏等只要求单线程快的负载,它帮助不大,有时还会抢资源。在大小核设计里,它还让操作系统的调度变得更复杂。
现状与未来。两家走向分岔。Intel 2024 年的 Lunar Lake 和 Arrow Lake 去掉了大核的超线程:Intel 的理由是省下的面积和功耗可以让大核更强,多线程吞吐交给数量众多的能效核。AMD 的 Zen 5 依旧保留 SMT。服务器上 SMT 仍然很重要,据报道 Intel 计划在之后的 Xeon 中让它回归。
频率撞墙之后,只能多请几个工人
2005 年,Intel 和 AMD 不约而同地把两颗核心放进了一颗 CPU。
为什么诞生。芯片的动态功耗大约和“电压的平方 × 频率”成正比。频率要提高,电压往往也得提高,功耗就像滚雪球一样涨。2004 年,Intel 的 Pentium 4(Prescott)功耗超过 100 瓦,原计划冲上 4 GHz 以上的后续产品 Tejas 被取消。业界意识到:与其让一个核心跑得更快,不如放两个核心各跑一份活。IBM 在 2001 年的 POWER4 上已经做出双核;2005 年 4 月 AMD 发布双核 Opteron,5 月 Intel 发布 Pentium D(其实是两颗芯片装在一个封装里),随后 AMD 推出 Athlon 64 X2。
它解决了什么。在功耗不变的前提下继续提高总算力。今天桌面 CPU 有 16 到 24 个核心;服务器 CPU 更夸张:AMD EPYC 9965(2024)有 192 个核心,Intel Xeon 6 的能效核版本最多 288 个核心。
它的缺陷。软件必须改写成“多线程”才能用上多核,很多程序做不到。1967 年 Gene Amdahl 指出:程序里只要有一部分必须按顺序执行,再多的核心也帮不上那一部分,这叫阿姆达尔定律。比如一个程序 10% 只能串行,那么无论有多少核心,最多只能快 10 倍。核心越多,彼此通信、共享缓存、保持数据一致也越难,芯片越大良率越低,这直接催生了 芯粒。
现状与未来。核心数仍在涨,但方式变了:一是把多个小芯片拼起来(AMD 的 CCD 芯粒、Intel 的 tile);二是大小核混搭(Intel 的 P 核 + E 核、AMD 的 Zen 与 Zen c),详见 Intel 路线和 AMD 路线。
把“管内存的人”请进 CPU
以前 CPU 要数据,得先找主板上的“北桥”转达。2003 年 AMD 把这个中间人取消了。
为什么诞生。内存控制器是负责和内存条“对话”的电路:发地址、收数据、按时刷新。2003 年以前,它放在主板上一颗叫北桥的芯片里,CPU 通过前端总线(FSB)和北桥相连。一次读内存要走两段路,还要和显卡、硬盘等争抢同一条总线。核心越多,这条总线越堵。2003 年 AMD 的 K8(Opteron 和 Athlon 64)把内存控制器直接做进 CPU,并用 HyperTransport 连接芯片组。Intel 直到 2008 年的 Nehalem(第一代 Core i7)才跟进,同时用 QPI 取代了 FSB。
它解决了什么。内存延迟据当年测试降低了数十纳秒,带宽随核心数一起增长(每颗 CPU 自带内存通道,多路服务器的总带宽成倍增加)。这是 Athlon 64 和 Opteron 在 2003–2006 年压过 Pentium 4 的重要原因之一,Intel 在 Nehalem 上补课后也收获了巨大提升。
它的缺陷。CPU 和内存类型绑死了:内存从 DDR 换到 DDR2,AMD 就得出新 CPU 和新插槽(2006 年的 AM2)。多路服务器里,每颗 CPU 只直接连自己的内存,访问“别人家”的内存要绕路,这叫 NUMA(非一致内存访问),软件得特别优化。
现状与未来。今天所有 x86 CPU 都集成了内存控制器。有意思的是,它又“搬了一次家”:AMD 从 2019 年 Zen 2 起把它放在单独的 I/O 芯粒(IOD)上,Intel 的 Meteor Lake 放在 SoC tile 上。它仍在同一个封装里,只是不和计算核心挤在一颗芯片上。下一步是内存本身也搬进封装(Lunar Lake、Apple M 系列),以及服务器上的 CXL 内存扩展。
有余力就自动超频
CPU 很少满负荷运行。睿频的想法是:只有一两个核心在忙、温度还低时,把它们的频率临时拉高。
为什么诞生。多核时代出现了一个矛盾:标称频率要按“所有核心同时满载”来定,否则会过热;可日常很多程序只用一两个核心,其余核心闲着,散热和供电还有大把余量。2008 年 Intel 在 Nehalem 上推出 Turbo Boost(睿频加速):芯片里的电源管理单元实时监测温度、电流和功耗,有余量就自动把频率往上提。AMD 2010 年推出 Turbo Core,2017 年 Zen 起改为更精细的 Precision Boost,可以按 25 MHz 一档连续调节。
它解决了什么。兼顾了单线程和多线程:打开网页、玩游戏这类“少数核心很忙”的场景,频率能冲到 5.5–6 GHz;渲染、编译这类“全部核心都忙”的场景,频率回落但总量更大。它把散热和供电的余量变成了性能。
它的缺陷。性能变得不可预测:同一颗 CPU 装在散热差的机箱里,就会跑得慢一截。厂商为了榜单越推越激进,电压和温度一路走高。2024 年 Intel 确认部分第 13、14 代桌面酷睿出现不稳定,原因是微码要求的工作电压偏高,导致芯片加速老化,Intel 为此发布了多次微码更新,并把受影响型号的保修延长两年。
现状与未来。睿频已成为标配,而且越来越聪明:按每个核心的体质分别设定频率,按温度、电池状态,甚至按操作系统告诉它的“这个任务重要不重要”来调节。AMD 的 PBO、Curve Optimizer 让玩家可以自己调节加速曲线。
翻译过的句子,记下来下次直接用
x86 指令长短不一,翻译起来又慢又费电。把翻译结果存起来,循环再跑时就不用重新翻译了。
为什么诞生。在 CPU 入门 里讲过:x86 CPU 内部会把复杂的 x86 指令拆成简单的微操作(µop,读作“micro-op”)再执行。这个“拆”就是译码。麻烦在于 x86 指令的长度从 1 到 15 字节不等,CPU 拿到一串字节时,得先弄清楚每条指令从哪开始、到哪结束,才能并行译码。这就像读一段没有标点的文字,还要一眼读出好几句。相比之下,ARM 64 位指令一律 4 字节,切起来非常简单。
- 1µop 缓存:按地址存着已经拆好的微操作,命中时每拍能送出更多 µop,译码器可以休息省电。
- 2传统译码路径:第一次遇到的代码,必须一个字节一个字节地找边界、拆分,耗电且每拍条数有限。
演变。2000 年 Pentium 4 先尝试过一种“踪迹缓存”(trace cache),把一整段执行路径上的 µop 存起来,但它复杂又费面积,后来被放弃。2011 年 Sandy Bridge 换成更简单的 µop 缓存(约 1500 条 µop),一举成功。AMD 从 2017 年 Zen 起也采用(约 2000 条),之后几代不断扩大,Zen 4 约 6750 条。
它解决了什么。程序大部分时间在跑循环,同一段代码会重复成千上万次。µop 缓存命中率往往很高,命中时既绕过了最慢最费电的译码环节,又缩短了猜错分支后的恢复时间。它在很大程度上抹平了 x86“译码难”的先天劣势。
它的缺陷。占面积;容量有限,大型程序(数据库、浏览器)代码太多,装不下时又退回慢路径。2021 年弗吉尼亚大学等的研究(“I See Dead µops”)还演示了利用 µop 缓存的新型侧信道攻击。
现状与未来。Intel 和 AMD 的大核都有 µop 缓存,而且越做越大。AMD 的 Zen 5 还把译码器分成两组,可以同时译码两段预测好的代码。有趣的对照是:ARM 的部分新核心(如 Cortex-A715)因为指令定长、译码便宜,反而把这类缓存去掉了。这正是 x86 的未来 里“指令集到底有多重要”争论的一个注脚。
十二个发明:诞生、功劳、毛病、去向
| 技术 | 诞生 | 解决什么 | 缺陷 | 现状 / 去向 |
|---|---|---|---|---|
| 流水线 | 1960s 大型机;x86 i486(1989) | 各部件同时忙,频率可以提高 | 依赖和分支造成气泡;太长则猜错代价大 | 主流约 14–20 级 |
| 超标量 | CDC 6600(1964);Pentium(1993) | 突破每拍 1 条 | 越宽越难填满,面积功耗上升 | 主流大核约 6–8 宽 |
| 乱序执行 | Tomasulo(1967);Pentium Pro(1995) | 等内存时先做别的 | “记账”电路大、耗电 | 主流窗口约 500 条 |
| 分支预测 | 2 位计数器(1981);两级(1991) | 岔路不停车 | 猜错整批作废;随机数据难猜 | 主流感知机、TAGE |
| 推测执行 | 与乱序执行同期,P6(1995) | 让乱序窗口装满 | 2018 年 Spectre / Meltdown 侧信道 | 主流但加防护硬件补洞 |
| 缓存分级 | IBM 360/85(1968);i486 片上 L1(1989) | 内存墙 | 面积大,SRAM 难缩,一致性复杂 | 上升3D 堆叠缓存 |
| SIMD | MMX(1997)→ SSE → AVX → AVX-512 | 一次算一排数 | 碎片化、降频、大小核不一致 | 整合中AVX10 |
| SMT 超线程 | 学术 1995;Intel 2002;AMD 2017 | 填满空闲执行单元 | 侧信道;单线程无益 | 分岔Intel 客户端去掉,AMD 保留 |
| 多核 | POWER4(2001);x86 2005 | 频率墙后继续加算力 | 阿姆达尔定律;大芯片良率低 | 主流芯粒、大小核 |
| 集成内存控制器 | AMD K8(2003);Intel Nehalem(2008) | 去掉北桥,降延迟 | CPU 与内存类型绑定;NUMA | 主流移到 IOD / SoC tile |
| 睿频 | Intel 2008;AMD 2010 / 2017 | 把散热余量变成速度 | 性能不可预测,电压过高伤芯片 | 主流按核心精细调节 |
| µop 缓存 | P4 踪迹缓存(2000);Sandy Bridge(2011) | 绕过慢而费电的 x86 译码 | 占面积,容量有限,侧信道 | 上升越做越大 |
- 性能 = 频率 × IPC。2005 年频率撞墙后,进步主要来自 IPC 和核心数。
- 流水线、超标量、乱序执行负责“每拍多干活”;分支预测和推测执行负责“别断流”。
- 缓存和集成内存控制器负责“少等数据”,因为内存比 CPU 慢上百倍。
- SIMD、超线程、多核负责“多分身”,但都需要软件配合。
- 每个发明都有代价:面积、功耗、复杂度,以及 2018 年起被重视的安全问题。
你的电脑每秒都在用它们
打开任务管理器,“内核”和“逻辑处理器”数量不同,就是超线程在起作用;如果两个数相同(比如 Intel Core Ultra 200S 系列),说明这颗 CPU 没有超线程。看视频时 CPU 占用很低,是因为解码交给了专用硬件和 SIMD 指令。游戏玩家爱买带 “X3D” 的 AMD 处理器,买的就是那层叠上去的大缓存。2018 年初你的电脑突然收到一批“安全更新”,就是在修 Spectre 和 Meltdown。
1. 流水线为什么能让 CPU 变快?它让每条指令本身变快了吗?
没有。每条指令仍要走完所有步骤。流水线让不同指令的不同步骤同时进行,每拍都能完成一条,提高的是吞吐量;同时每一级的活变少,频率也能更高。
2. 乱序执行和推测执行分别解决什么问题?
乱序执行让不相关的指令在前面的指令等待(比如等内存)时先做;推测执行让 CPU 沿着分支预测的方向先执行下去,这样乱序引擎才有足够多的指令可选。
3. Spectre 攻击中,秘密是怎么“漏”出来的?
推测执行时 CPU 读到了秘密,并用它去访问内存,把对应的数据带进了缓存。猜错后寄存器结果被撤销,但缓存里的痕迹没有撤销。攻击者测量哪个位置读得特别快,就能推出秘密值。
4. 如果 L1 命中率从 95% 降到 90%,平均等待时间大约怎么变?
未命中的比例从 5% 变成 10%,翻了一倍,平均等待时间里“未命中”那部分也大约翻倍。用上面的计算器(L2 80%、L3 70%)可以看到,平均等待从约 1.6 ns 升到约 2.2 ns。
5. 为什么 2005 年前后 CPU 开始走多核路线?多核有什么限制?
功耗大约与电压平方乘以频率成正比,频率再往上提,功耗和发热失控(Pentium 4 后续的 Tejas 被取消)。多核在相同功耗下提供更多算力,但受阿姆达尔定律限制:程序里必须串行的部分,再多核心也帮不上忙。
6. x86 为什么特别需要 µop 缓存,而一些 ARM 核心可以不要?
x86 指令长度 1 到 15 字节不等,并行译码要先找边界,既慢又费电。µop 缓存把译好的结果存起来,下次直接用。ARM 64 位指令固定 4 字节,译码便宜,所以部分 ARM 核心去掉了类似的缓存。
延伸阅读
- J. L. Hennessy、D. A. Patterson,Computer Architecture: A Quantitative Approach(第 6 版,2017),流水线、乱序执行、缓存、SMT 各章。
- R. M. Tomasulo,“An Efficient Algorithm for Exploiting Multiple Arithmetic Units”,IBM Journal,1967;J. E. Smith,“A Study of Branch Prediction Strategies”,ISCA 1981;T.-Y. Yeh、Y. N. Patt,两级自适应分支预测,MICRO 1991;D. A. Jiménez、C. Lin,感知机分支预测,HPCA 2001;A. Seznec,TAGE 预测器,2006。
- W. A. Wulf、S. A. McKee,“Hitting the Memory Wall: Implications of the Obvious”,ACM SIGARCH Computer Architecture News,1995。
- D. M. Tullsen、S. J. Eggers、H. M. Levy,“Simultaneous Multithreading: Maximizing On-Chip Parallelism”,ISCA 1995;Intel Hyper-Threading 技术白皮书(2002)。
- P. Kocher 等,“Spectre Attacks: Exploiting Speculative Execution”;M. Lipp 等,“Meltdown: Reading Kernel Memory from User Space”,2018;Google Project Zero 博客(2018 年 1 月 3 日)。
- Intel 64 与 IA-32 架构优化参考手册;Intel AVX10 架构规范(2023 年发布,2025 年修订);Intel 关于第 13、14 代桌面处理器不稳定问题的说明(2024)。
- AMD Zen、Zen 4、Zen 5 微架构发布资料(Hot Chips 2017、2023、2024);Agner Fog,The microarchitecture of Intel, AMD and VIA CPUs;Chips and Cheese 对各代核心的测试文章。
- G. M. Amdahl,“Validity of the single processor approach to achieving large scale computing capabilities”,AFIPS 1967。
- X. Ren 等,“I See Dead µops: Leaking Secrets via Intel/AMD Micro-Op Caches”,ISCA 2021。
- 本站相关页面:CPU 入门、x86 五十年、走进死胡同的路线、Intel 路线、AMD 路线、x86 的未来、晶体管。