【问题标题】:Multiple accesses to main memory and out-of-order execution多次访问主存和乱序执行
【发布时间】:2016-08-27 15:52:53
【问题描述】:

让我们假设我有两个指向不相关地址的指针,这些地址没有被缓存,所以当被取消引用时,它们都必须从主内存一路来。

int load_and_add(int *pA, int *pB)
{
    int a = *pA;   // will most likely miss in cache
    int b = *pB;   // will most likely miss in cache 

    // ...  some code that does not use a or b

    int c = a + b;
    return c;
}

如果乱序执行允许在计算 c 的值之前执行代码,那么如何在现代英特尔处理器上获取值 ab

潜在的流水线内存访问是否已完全序列化,或者 CPU 的内存控制器是否执行了某种获取重叠?

换句话说,如果我们假设访问主存需要 300 个周期。获取ab 会花费600 个周期,还是乱序执行会导致一些可能的重叠并且可能花费更少的周期?

【问题讨论】:

  • 编辑使用正确的术语。例如。 “命中”通常用于描述缓存命中,因此“命中主存”在略读时不容易解析。当内存地址是连续的时,通常会使用“连续”。问题是它们是否被并行处理(流水线)。
  • 感谢@PeterCordes,非常棒的改写。我真的很难写出这个问题,但事实上,我试图了解的底线是内存读取是否是并行处理的。
  • 不用担心,如果您还没有足够的知识自行搜索并找到答案,通常很难以“正确”的方式提出问题:P

标签: performance intel cpu-architecture memory-access


【解决方案1】:

现代 CPU 具有多个负载缓冲区,因此可以同时处理多个负载。内存子系统是大量流水线的,它的许多部分提供了比延迟更好的吞吐量。 (例如,通过预取,Haswell 可以维持(从主存储器)每 1 个时钟的 8B 负载。但是如果提前不知道地址,则延迟是数百个周期)。

所以是的,Haswell 内核可以跟踪多达 72 个等待来自缓存/内存的数据的未完成负载微指令。 (这是每个内核的。共享的 L3 缓存还需要一些缓冲区来处理整个系统对 DRAM 和内存映射 IO 的加载/存储。)

Haswell's ReOrder Buffer size is 192 uops,因此code that does not use a or b 中最多可以发出和执行 190 uop 的工作,而 ab 的负载是尚未退役的最旧指令。为了支持precise exceptions,指令/微指令已停用。 ROB 大小基本上是无序窗口的限制,用于隐藏缓存未命中等慢速操作的延迟

另请参阅 标签 wiki 上的其他链接,了解 CPU 的工作原理。 Agner Fog 的微架构指南非常适合建立 CPU 管道的心智模型,让您大致了解代码将如何执行。

来自David Kanter's Haswell writeup

【讨论】:

  • 可能值得注意的是,miss under miss(即在缓存未命中后启动第二个缓存丢失内存访问)不需要乱序执行;它只需要一个记分板来跟踪加载的值尚不存在(但一旦要使用这些值,执行就会停止)。如果只有记分板,第二次访问的 TLB 未命中将阻止内存并行性,因为无法保证精确的异常。 (历史或未来的文件,同时仍按顺序发布将允许这样的推测。)
猜你喜欢
  • 1970-01-01
  • 2012-09-12
  • 2011-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多