在汇编程序和处理程序的研究中,有一件事把我带出来,如何完成指令:
add mem, 1
在我的脑海中,处理器无法加载内存值 and 处理同一指令期间的算术运算 . 所以我觉得它发生在:
mov reg, mem
add reg, 1
mov mem, reg
如果我考虑使用RISC Pipeline的处理器,我们可以观察到一些停顿 . 像 i++
这样简单的指令令人惊讶:
| Fetch | Decode | Exec | Memory | WriteB |
| Fetch | | | Decode | Exec | Memory | WriteB |
| Fetch | | | | Decode | Exec | Memory | WriteB |
(正如我在Patterson的书“计算机体系结构:量词方法”中所读到的那样,寄存器在 Decode uOp中读取,存储/加载到存储器uOp中,我们允许自己在存储器uOp中获取寄存器的值 . )
我对吗?还是现代处理器有更具效的方法来做到这一点?
1 回答
你没错,现代的x86会将
add dword [mem], 1
解码为3 uops:一个加载,一个ALU添加和一个商店 .这3个相关操作不能同时发生,因为后者必须等待前一个操作的结果 .
但独立指令的执行可以重叠,现代CPU非常积极地寻找并利用"instruction level parallelism"以比每个时钟1 uop更快的速度运行代码 . 请参阅this answer for an intro to what a single CPU core can do in parallel,其中包含更多内容的链接,例如Agner Fog's x86 microarch guide,以及David Kanter撰写的Sandybridge和Bulldozer .
But if you look at Intel's P6 and Sandybridge microarchitecture families, a store is actually separate store-address and store-data uops . store-address uop不依赖于load或ALU uop,并且可以随时将存储地址写入存储缓冲区 . (英特尔的优化手册将其称为内存订购缓冲区) .
为了增加前端吞吐量,存储地址和存储数据uop可以解码为微融合对 . 对于
add
,加载alu操作也是如此,因此Intel CPU可以将add dword [rdi], 1
解码为2个融合域uop . (相同的负载添加微融合用于将add eax, [rdi]
解码为单个uop,因此"simple"解码器中的任何一个都可以解码它,而不仅仅是可以处理多uop指令的"complex"解码器 . 这减少了前端瓶颈) .这就是
add [mem], 1
在Intel CPU上比inc [mem]
更有效的原因,尽管inc reg
与add reg,1
一样高效(但更小) . (inc
不能微量融合其load inc,它设置的标志与add
不同) . INC instruction vs ADD 1: Does it matter?但这只是帮助前端更快地进入调度程序;负载仍然必须与add分开运行 .
但微熔合负载并没有准备就绪 . 考虑像
add [rdi], eax
这样的指令,其中RDI和EAX都是指令的输入,但EAX不是自由加载执行单元(AGU缓存访问) . 另见How are x86 uops scheduled, exactly? .所有当前的x86微体系结构都使用寄存器重命名(Tomasulo算法)进行无序执行 . 指令被重命名并发布到核心的无序部分(ROB和调度程序) .
在从调度程序“执行”指令到执行单元之前,不读取物理寄存器文件 . (或者对于最近生成的输入,从其他uops转发 . )
Independent instructions can overlap their execution . 例如,Skylake CPU可以维持每个时钟4个融合域/ 7个非融合域uop的吞吐量,包括2个负载1个存储,in a carefully crafted loop:
Sandybridge系列CPU具有L1d高速缓存,每个时钟可读取2次读取 . (在Haswell之前,只有256位向量可以解决AGU吞吐量限制 . 请参阅How can cache be that fast? . )
Sandybridge系列前端吞吐量是每个时钟4个融合域uop,并且它们在后端有许多执行单元来处理各种指令混合 . (Haswell后来有4个整数ALU,2个加载端口,一个存储数据端口和一个专用存储AGU,用于简单的存储寻址模式 . 因此,它们经常可以在缓存未命中执行后快速“赶上”,快速制作在无序窗口的房间找到更多工作要做 . )