performance - 存储转发地址与数据 : What the difference between STD and STA in the Intel Optimization guide?

标签 performance assembly optimization intel cpu-architecture

我想知道是否有任何英特尔专家可以告诉我 STD 和 STA 在英特尔 Skylake 核心方面的区别。

在 Intel 优化指南中,有一张图片描述了 Intel Cores 的“超标量端口”。

Here's the PDF .图片在第 40 页。

Here's a picture of the relevant graphic .

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 工作以及指令如何解码并通过管道。另请参阅 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 并从那里读取它。
  • How does store to load forwarding happens in case of unaligned memory access?
  • Store-to-Load Forwarding and Memory Disambiguation in x86 Processors

  • 当函数在调用函数之前溢出一些寄存器时,可能会发生存储/重新加载,作为在堆栈上传递参数的一部分(尤其是在堆栈上传递所有参数的糟糕堆栈参数调用约定)。或者通过引用非内联函数传递一些东西。或者在直方图中,如果重复命中同一个 bin,则基本上是在循环中执行内存目标增量。

    关于performance - 存储转发地址与数据 : What the difference between STD and STA in the Intel Optimization guide?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47701898/

    相关文章:

    c# - .NET 探查器如何工作?

    java - 为什么哈希函数不使用随机性?

    assembly - 我们怎样才能知道这个处理器支持多少内存呢?

    optimization - R 中的并行优化

    postgresql - 查看并清除 Postgres 缓存/缓冲区?

    c# 如何避开内存分配瓶颈以提高多线程性能

    sql - SSIS 预评估阶段需要很长时间

    optimization - 如何优化我的 C/x86 代码?

    dart - 为什么我的 asm 校验和宏的 Dart 实现不起作用?

    php - 优化数组合并操作