如何使用(读/写)CPU缓存L1,L2,L3

时间:2016-10-27 19:38:44

标签: cpu cpu-usage cpu-architecture cpu-cache cpu-cores

我的任务需要超高性能

当然我可以优化其算法,但我也希望优化硬件级别。

我当然可以使用CPU亲和性来将整个核心分配给处理我的任务的线程

另一种优化可能是将CPU缓存(L1,L2,L3)放入我的任务需要完成的数据中,以尽可能避免" RAM访问"延迟

我可以使用哪种API进行此类开发?

(换句话说,我的问题可能是:"如何强制CPU在缓存中放置给定的数据结构?")

感谢您的帮助

3 个答案:

答案 0 :(得分:2)

通常不能覆盖CPU缓存中的LRU替换策略。 x86 CPU至少不支持将某些地址范围“固定”到任何级别的缓存中。

您可以做的是在使用前“预取”。 “软件预取”很少有用。通常,HW预取功能很好,只要缓存占用空间足够小,您的数据就会保留在缓存中。 Ulrich Drepper的What every programmer should know about memory涵盖了这一点,并且仍然具有相关性。但是,它强调软件预取(特别是一个单独的预取线程)适用于P4,但对其他CPU来说并不是一个好主意。在阅读时请记住这一点。

将数据结构和访问模式设计为​​缓存友好非常重要。尝试谷歌搜索“缓存感知”算法,也许(或只是阅读乌尔里希的论文)。或者只是随意调整,使用性能计数器来查看是否意外地做了导致大量缓存未命中的事情。

如果您在Intel Haswell Xeon或更新版本(Exxx v3或更高版本)上运行此操作,则可以对L3缓存进行分区,以便运行您的关键线程的核心拥有一大块L3,并且不会被驱逐出来其他核心。这称为CAT (Cache Allocation Technology)。另请参阅this article by Dan Luu

答案 1 :(得分:2)

Peter C关于预取的优秀评论。作为以前的优化器,我们要做的第一件事就是删除所有的SW预取。此外,不要尝试使用电源状态等。他们现在非常好,以至于努力不值得HPC获益。可能的例外是超线程。你想要去那里的唯一时间是某些基准测试,你需要一致性和性能。

查看英特尔优化资源,例如optimization guide。也让自己成为一个好的探测器; Intel's VTune确实是最好的之一。有关英特尔的信息,请使用bing(或google)查找内容。英特尔的网站一直是一个光滑的混乱。 VTune拥有学生和教育者许可。

以下是我在优化应用程序性能时所采取的步骤。首先,耗尽更高级别的软件更改。然后深入调整硬件性能。为什么?有两个原因:(1)代码更改通常与架构无关,并且更有可能在迁移到不同的HW平台和生成时幸存。 (2)它们很简单(尽管可能不那么有趣)。

代码更改:

  1. 删除所有SW预取。
  2. 使用定期中断替换任何轮询
  3. 确保所有检查中断都有适当的间隔
  4. 使用Fortran。真。 Fortran还活着的原因。看看英特尔Fortran论坛。该论坛的所有经典HPC。英特尔的Fortran编译器是最好的之一。
  5. 使用优秀的优化编译器,并使用编译器设置和编译指示/注释(例如#pragma loop count)。同样,英特尔是最好的之一。 (我讨厌这样说,但这是真的。)
  6. 使用优秀的SW分析器查找优化机会(大部分时间都用在哪里)。确保分析器能够深入了解源代码,以确定在不同功能中花费的时间。首先优化这些功能。
  7. 找到适当确定核心数量的线程并行化(多线程)的机会
  8. 寻找矢量化的机会
  9. 从AoS(结构数组)转换为SofA。请注意,如果您必须动态进行转换,则可能不值得花费性能。
  10. 构造循环,使它们更有利于编译器查找矢量化机会。有关如何执行此操作,请参阅任何优秀的优化书。
  11. 硬件黑客/优化(使用优秀的硬件级性能分析器)

    1. 识别缓存和TLB未命中,并重新构建代码。
    2. 识别分支错误预测并重新构建代码。
    3. 识别管道停顿并重新构建代码。
    4. 最后一个建议,虽然我相信你已经知道了。记住,去追寻最热门的景点。较小的机会是耗时的,并且性能改进不会对整个应用程序产生影响。

      祝你好运。优化可以是有趣和有益的(如果你有点疯狂)。

答案 2 :(得分:1)

好吧,你需要使用一种低级语言(在这种情况下,C可能是最佳选择)。

然后你有一些阅读要做:What every programmer should know about memory。请特别注意第6章,其中包含有关如何针对特定使用模式进行优化的非常有用的编程建议。