5

我正在查看一些稍微混淆的代码,这些代码尝试使用各种编译器内置函数对预取指令进行平台抽象。它最初似乎基于 powerpc 语义,分别使用 dcbt 和 dcbtst 读取和写入预取变体(这两个都在新的可选流操作码中传递 TH=0)。

在 ia64 平台上,我们可以阅读:

__lfetch(__lfhint_nt1, pTouch)

而写:

__lfetch_excl(__lfhint_nt1, pTouch)

这(读取与写入预取)似乎很好地匹配了 powerpc 语义(除了 ia64 允许临时提示)。

有点奇怪的是,有问题的 ia32/amd64 代码正在使用

prefetchnta

不是

prefetchnt1

就像该代码与 ia64 实现一致(我们的(仍然活动的)hpipf 端口和我们现在死掉的 windows 和 linux ia64 端口的代码中的 #ifdef 变体)。

由于我们正在使用 intel 编译器进行构建,因此通过切换到 xmmintrin.h 内置程序,我应该能够使我们的许多 ia32/amd64 平台保持一致:

_mm_prefetch( (char *)pTouch, _MM_HINT_NTA )
_mm_prefetch( (char *)pTouch, _MM_HINT_T1 )

...只要我能弄清楚应该使用什么时间提示。

问题:

  • 是否有读取与写入 ia32/amd64 预取指令?我在指令集参考中没有看到任何内容。

  • nt1、nt2、nta 时间变化中的一个是否更适合读取与写入预取?

  • 知道是否有充分的理由在 ia32/amd64 上使用 NTA 时间提示,而在 ia64 上使用 T1?

4

2 回答 2

1
  • 是否有读取与写入 ia32/amd64 预取指令?我在指令集参考中没有看到任何内容。

一些系统支持prefetchw写指令

  • nt1、nt2、nta 时间变化中的一个是否更适合读取与写入预取?

如果该行仅由调用线程使用,则无论您如何使用该行都无关紧要,读取和写入都可以使用它。上面提到的 prefetchw 的好处是它会带来线路并给予你对它的所有权,如果线路也被另一个核心使用,这可能需要一段时间。另一方面,提示级别与 MESI 状态正交,仅影响预取行的生存时间。如果您在实际访问之前很长时间预取并且不想在此期间丢失预取,或者在访问之前预取,并且不希望预取过多地破坏您的缓存,这很重要。

  • 知道是否有充分的理由在 ia32/amd64 上使用 NTA 时间提示,而在 ia64 上使用 T1?

只是推测-也许更大的缓存和激进的内存BW更容易受到不良预取的影响,您希望通过非临时提示来减少影响。考虑到您的预取器突然松动以获取它可以获取的任何内容,您最终会陷入垃圾预取中,这些预取会通过大量有用的缓存线。NTA 提示使它们相互超越,其余部分完好无损。

当然,这也可能只是一个错误,我无法确定,只有开发编译器的人才能确定,但​​出于上述原因,这可能是有道理的。

于 2013-10-19T10:53:53.597 回答
0

我能找到的关于 x86 预取提示类型的最佳资源是优秀的 ol' 文章What Every Programmer Should Know About Memory

在 x86 上的大多数情况下,读取和写入预取的指令没有不同。例外似乎是那些非时间对齐的,其中写入可以绕过缓存,但据我所知,读取将始终被缓存。

很难回溯为什么早期的代码所有者在某个架构上使用一个提示而不是另一个提示。他们可能会假设该系列中的处理器上有多少缓存可用,那里的二进制文件的典型工作集大小,长期控制流模式等......并且不知道有多少这些假设得到了良好的支持推理或数据。从这里有限的背景来看,我认为你有理由采用对你现在正在开发的平台最有意义的方法,不管在其他平台上做了什么。当您考虑像这样的文章时尤其如此,这不是我听说它真的是唯一的上下文,

是否有更多事先知道的详细信息,例如使用此代码时的典型缓存未命中率,或者预计有多少预取会有所帮助?

于 2012-09-16T04:47:59.807 回答