我想知道是否有任何英特尔专家可以告诉我 STD 和 STA 在英特尔 Skylake 核心方面的区别。
在 Intel 优化指南中,有一张图片描述了 Intel Cores 的“超标量端口”。
Here's the PDF .图片在第 40 页。
.
Here's another picture from page 78 ,这张图描述了“店铺地址”和“店铺数据”:
考虑到 Skylake 每个时钟周期可以执行 #1 3x,但每个时钟周期只能执行 #2 一次,我很好奇这两者之间有什么区别。
对我来说,对数据地址进行存储转发似乎是“自然的”。但我无法理解何时会完成对数据(又名:STD/端口 4)的存储转发。是否有任何组装/优化专家可以帮助我准确理解 STD 和 STA 之间的区别?
最佳答案
自第一个 P6 系列微体系结构 Pentium Pro 出现以来,Intel CPU 一直将存储拆分为存储地址和存储数据。
但是存储地址和存储数据微指令可以微融合为一个融合域微指令。在 Sandy/IvyBridge 上,索引寻址模式未分层,如英特尔优化手册中所述。但是 Haswell 和后来的人甚至可以在 ROB 中保持它们微融合,因此它们不是未层压的。见 Micro fusion and addressing modes . (英特尔没有提到这一点,Agner Fog 还没有时间对 Haswell/Skylake 进行广泛的测试,所以 his usually-good microarch PDF 甚至根本没有提到取消层压。但你仍然应该阅读它以了解更多关于如何uops 工作以及指令如何解码并通过管道。另请参阅 x86 tag wiki 中的其他 x86 性能链接)
Considering that Skylake can perform #1 3x per clock cycle, but can only perform #2 once per clock cycle
端口 2 和 3 也可以运行 load uops 在他们的 AGU 上,让端口的加载数据部分在那个周期未使用。 Port7 只有一个用于简单寻址模式的专用存储 AGU。
带有变址寄存器的存储寻址模式不能使用端口 7,只能使用 p2/p3。但是,如果您确实对存储使用“简单”寻址模式,则峰值吞吐量为每个时钟 2 次加载 + 1 次存储。
在 Nehalem 和更早版本(P6 系列)上,p2 是唯一的加载端口,p3 是存储地址端口,而 p4 是存储数据。
在 IvyBridge/Sandybridge 上,没有用于存储地址 uops 的单独端口,它们总是在加载端口 (p23) 中的 AGU(地址生成单元)上运行。对于 256b 加载/存储,仅每隔一个周期需要 AGU(256b 加载或存储 uop 占用加载或存储数据端口 2 个周期,但加载端口可以在第二个周期接受存储地址 uop)。因此,理论上每个时钟 2 个加载/1 个存储在 Sandybridge 上是可持续的,但前提是其中大部分是使用 AVX 256 位矢量加载/存储作为两个 128 位一半运行。
Haswell 在端口 7 上添加了专用存储 AGU,并将加载/存储执行单元扩展到 256b,因为如果负载供应稳定,当加载端口不需要它们的 AGU 时,就没有空闲周期。
存储地址 uop 将地址(和宽度,我猜)写入存储缓冲区 (也就是英特尔术语中的内存顺序缓冲区)。让这件事单独发生,甚至可能在要存储的数据准备好之前,让稍后的加载(按程序顺序)检测它们是否与存储重叠。
当存在地址未知的待处理存储时无序执行加载是有问题的:错误的猜测意味着必须回滚管道。 (我认为
machine_clears.memory_ordering
perf counter 事件包括这个。可以从单线程代码中获得非零计数,但我忘记了我是否有明确的证据表明 Skylake 有时会推测性地猜测负载不重叠未知-地址商店)。正如大卫坎特指出的那样in his Haswell microarch writeup ,加载 uop 还需要探测存储缓冲区以检查转发/冲突,因此仅运行存储地址 uops 的执行单元的构建成本更低。
无论如何,我不确定对性能的影响是什么 如果英特尔重新设计,那么 port7 有一个完整的 AGU 可以处理索引寻址模式,也可以使存储地址 uops 只在 p7 上运行,而不是 p2/p3。
这将阻止存储地址 uops“窃取”p23,这确实发生了,并将最大持续 L1D 带宽从 96 字节/周期(2 次加载 + 1 次存储 32 字节 YMM 向量)减少到 Skylake 的 ~81 字节/周期根据英特尔优化手册中的表格。但在合适的情况下,Skylake can sustain 2 loads + 1 store per clock of 4-byte operands ,所以也许 81 字节/周期数受到其他一些微架构限制。峰值是 96B/时钟,但显然这不能无限期地背靠背发生。
阻止存储地址 uops 在 p23 上运行的一个缺点是,知道存储地址需要更长的时间,可能会延迟加载更多。
I can't understand when store-forwarding on the data (aka: STD / Port 4) would ever be done.
存储/重新加载可以让加载从存储缓冲区中获取数据,而不是等待它提交到 L1D 并从那里读取它。
当函数在调用函数之前溢出一些寄存器时,可能会发生存储/重新加载,作为在堆栈上传递参数的一部分(尤其是在堆栈上传递所有参数的糟糕堆栈参数调用约定)。或者通过引用非内联函数传递一些东西。或者在直方图中,如果重复命中同一个 bin,则基本上是在循环中执行内存目标增量。
关于performance - 存储转发地址与数据 : What the difference between STD and STA in the Intel Optimization guide?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47701898/