【问题标题】:The prefetch instruction预取指令
【发布时间】:2011-03-08 13:34:34
【问题描述】:

似乎预取使用的一般逻辑是可以添加预取,前提是代码正忙于处理,直到预取指令完成其操作。但是,如果使用过多的预取指令,似乎会影响系统的性能。我发现我们首先需要有没有预取指令的工作代码。稍后我们需要在代码的各个位置对预取指令进行各种组合并进行分析,以确定由于预取而实际可以改善的代码位置。有没有更好的方法来确定应该使用预取指令的确切位置?

【问题讨论】:

  • 你可能想说你指的是哪个CPU
  • 我正在寻找基于 ARM 和 MIPS 架构的 CPU。
  • 具体来说 - 它是 OMAP 5912 和 PIC32 的 ARM 内核

标签: assembly embedded arm mips prefetch


【解决方案1】:

在大多数情况下,预取指令几乎没有好处或没有好处,在某些情况下甚至会适得其反。大多数现代 CPU 都有一个自动预取机制,该机制运行良好,添加软件预取提示几乎无法实现,甚至会干扰自动预取,并且实际上会降低性能。

在一些极少数情况下,例如当您流式传输大块数据而您对其进行的实际处理很少时,您可能会设法通过软件启动的预取来隐藏一些延迟,但很难做到正确 -您需要在使用数据之前启动数百个周期的预取 - 做得太晚,您仍然会出现缓存未命中,做得太早,您的数据可能会在您准备好使用之前从缓存中被逐出.通常这会将预取放在代码的一些不相关的部分,这不利于模块化和软件维护。更糟糕的是,如果您的架构发生变化(新的 CPU、不同的时钟速度等),例如 DRAM 访问延迟增加或减少,您可能需要将预取指令移动到代码的另一部分以保持它们的有效性。

无论如何,如果你觉得你真的必须使用预取,我建议在任何预取指令周围使用#ifdefs,这样你就可以在有和没有预取的情况下编译你的代码,看看它是否真的有助于(或阻碍)性能,例如

#ifdef USE_PREFETCH
    // prefetch instruction(s)
#endif

不过,总的来说,我建议您在完成所有更高效和明显的工作之后,将软件预取放在次要位置,作为最后的微优化手段。

【讨论】:

  • 没错,也有很多预取可能不好的情况。也就是说,假设数据 w,x,y,z 是否按照软件要求的顺序预取。但是,由于缓存内存的大小,z 可能会从缓存中逐出 y,因此即使预取 y 也可能不可用影响访问(延迟)并因此影响预取位置。是的,与预取(软件)使用相关的问题很难解决。但是,如何以简单的方式获得正确的预取位置?
  • 根据我的经验,没有简单的方法,而且在大多数情况下,这种努力是不合理的。通过改进算法及其实现、注意缓存使用和内存访问模式、使用 SIMD 等,您可以获得更多的“物超所值”的优化。
  • @Zan Lynx:您是否使用不同的 CPU 和不同的时钟速度进行了测试?较旧的 CPU 可能会从手动预取中受益,但对于更现代的 CPYU,很难改进自动预取。它在某种程度上还取决于 CPU 速度和内存带宽/延迟等,因此对一种配置的明显改进可能不适用于其他配置。
  • @Paul R:Core2 和 Itanium 都受益于预取。我没有消除获取延迟,但它确实减少了树搜索中的等待周期数。
  • @Zan Lynx:在某些情况下可能会受益,但重要的是要记住,只有如果你有可用的内存带宽,你才能利用预取 - 在在许多情况下(可能是大多数情况下),您通过手动预取实现的所有目的都是从程序的其他部分夺走带宽。但是,如果它在您的特定情况下对您有用,那就太好了。
【解决方案2】:

当然,您必须进行一些实验,但并不是说您需要在需要数据之前获取一些百周期 (100-300)。 L2 缓存足够大,预取的数据可以在那里停留一段时间。

这种预取在循环之前非常有效(当然是几百个循环),特别是如果它是内部循环并且循环每秒启动数千次甚至更多次。

此外,对于您的快速 LL 实现或树实现而言,预取可能会获得可衡量的优势,因为 CPU 不知道 jet 很快需要数据。

但请记住,预取指令会占用一些解码器/队列带宽,因此过度使用它们会损害性能。

【讨论】:

  • 是的,我发现预取在 B+Tree 搜索中非常有用。块中的二分查找在比较中需要足够的时间,并且分支未命中,即数据在 L2 中不是在需要时准备好,但比没有预取要早。
【解决方案3】:

甚至考虑预取代码性能肯定已经是一个问题。

1:使用代码分析器。尝试在没有分析器的情况下使用预取是浪费时间。

2:每当您在关键位置发现异常缓慢的指令时,您就有了预取的候选。通常,实际问题出在慢行之前的内存访问,而不是分析器所指示的慢行。找出导致问题的内存访问(并不总是那么容易)并预取它。

3 再次运行您的分析器,看看它是否有任何不同。如果没有取出来。 有时我以这种方式将循环速度提高了 300% 以上。如果您有一个以非顺序方式访问内存的循环,这通常是最有效的。

我完全不同意它在现代 CPU 上的用处不大,我发现完全相反,虽然在旧 CPU 上预取大约 100 条指令是最佳的,但现在我将这个数字设置为 500 左右。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-10
    • 2014-05-06
    • 2018-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多