Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 指令缓存加载和逐出规则_C_Performance_Assembly_Cpu Cache_Micro Architecture - Fatal编程技术网

C 指令缓存加载和逐出规则

C 指令缓存加载和逐出规则,c,performance,assembly,cpu-cache,micro-architecture,C,Performance,Assembly,Cpu Cache,Micro Architecture,我试图了解指令缓存是如何工作的 在执行代码块时,预取了多少额外的缓存线?它是否考虑了分支预测 如果代码块包含函数调用,函数代码体是按顺序加载的还是在缓存的不同部分中加载的 例如,以下代码片段是否相同 if (condition) { // block of code that handles condition } 及 如果条件很少为真,那么哪种方法可以减少指令序列中的“漏洞” 如果我的第一个示例是经常运行的代码的一部分,并且If条件从来都不是真的,那么If条件的主体最终会被逐出

我试图了解指令缓存是如何工作的

  • 在执行代码块时,预取了多少额外的缓存线?它是否考虑了分支预测

  • 如果代码块包含函数调用,函数代码体是按顺序加载的还是在缓存的不同部分中加载的

例如,以下代码片段是否相同

 if (condition) {
   // block of code that handles condition
}

如果条件很少为真,那么哪种方法可以减少指令序列中的“漏洞”

  • 如果我的第一个示例是经常运行的代码的一部分,并且
    If
    条件从来都不是真的,那么
    If
    条件的主体最终会被逐出,而代码主体的其余部分保持原样吗

我假设这些问题没有取决于特定微体系结构的答案。但如果有,我有一个x86-64 Intel Sandy Bridge。

事实上,答案在很大程度上取决于微体系结构。这不是x86或任何其他体系结构定义的东西,而是留给设计师在不同的世代中实现和改进

对于沙大桥,你可以找到一个有趣的描述 最相关的部分是-

Sandy Bridge的指令获取如上图2所示。分支预测在取指令之前稍早排队,因此所取分支的暂停通常是隐藏的,这是早期在Merom和Nehalem中使用的特性。对32B条指令进行预测,同时从一级指令缓存每次提取16B条指令

一旦知道下一个地址,Sandy Bridge将探测uop缓存(我们将在下一页讨论)和一级指令缓存。一级指令缓存为32KB,64B行,关联性增加到8路,这意味着它实际上是索引和物理标记的。L1 ITLB在小页面的线程之间进行分区,每个线程有专用的大页面。Sandy Bridge为大页面添加了2个条目,使4KB页面(两个线程)的条目总数达到128个,大页面(每个线程)的条目总数达到16个

换句话说,正如图中所示,分支预测是管道的第一步,在指令缓存访问之前。因此,缓存将保存分支预测器预测的地址“跟踪”。如果某个代码片段很难被访问,预测器将避免它,并且随着时间的推移,它将从I-cache中过时。因为分支预测器应该能够处理函数调用,所以代码片段之间应该没有根本的区别

这当然是由于对齐问题(I-cache有64B行,不能有部分数据,因此内联代码实际上可能比函数调用造成更多无用的开销,尽管两者都是有界的),当然也是由于错误的预测。
也有可能其他硬件预取器正在工作,可能会将数据提取到其他级别,但这并不是官方披露的内容(指南仅提到一些二级缓存预取,可能有助于减少延迟,而不会影响一级缓存)。还要注意的是,Sandy bridge有一个uop缓存,它可能会增加更多缓存(但也更复杂)。

现代评测编译器肯定会尝试将热路径打包到尽可能少的缓存块中。我建议您阅读函数内联。@EOF-我指的是函数没有内联的情况。@BenVoigt-在这种情况下,编译器不知道该块是否是热路径的一部分,可以使用
gcc
clang
扩展来标记
不太可能
等情况。查看此帖子:
if (condition) {
    handle_condition(); // function that handles the condition
}