让我们假设我有两个指向未缓存的无关地址的指针,因此在被解除引用时它们都必须从主存中一直到来。
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
的值之前执行代码,那么在现代英特尔处理器上如何获取值a
和b
?
潜在的流水线内存访问是完全序列化的还是CPU的内存控制器可能会出现某种提取重叠?
换句话说,如果我们假设击中主存储器需要300个周期。提取a
和b
会花费600个周期还是无序执行会导致一些可能的重叠并且可能会花费更少的周期?
答案 0 :(得分:3)
现代CPU具有多个负载缓冲区,因此可以同时实现多个负载。内存子系统采用大量流水线技术,使其中许多部分的吞吐量远远超过延迟。 (例如,通过预取,Haswell可以每1个时钟维持(从主存储器)一个8B负载。但是如果地址未提前知道的延迟是数百个周期。)
所以,是的,Haswell核心可以跟踪多达72个未完成的负载uops,等待缓存/内存中的数据。 (这是每个核心。共享L3缓存还需要一些缓冲区来处理整个系统对DRAM和内存映射IO的加载/存储。)
Haswell's ReOrder Buffer size is 192 uops,因此code that does not use a or b
和a
的加载量是b
和project.clj
的最早指令,因此:foreign-libs [{:file "https://rawgit.com/felixrieseberg/React-Spreadsheet-Component/master/dist/spreadsheet.js"
:provides ["no-idea"]}]
中最多可以执行190次uop工作退休了。指令/ uops已停用,以支持precise exceptions。 ROB大小基本上是无序窗口的限制,用于隐藏慢速操作(如缓存未命中)的延迟。
另请参阅x86标记wiki上的其他链接,了解CPU的工作原理。 Agner Fog的微型指南非常适合拥有CPU管道的心智模型,让您大致了解代码的执行方式。