我正在查看一些稍微混淆的代码,这些代码尝试使用各种编译器内置函数对预取指令进行平台抽象。它似乎最初基于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?
答案 0 :(得分:1)
- 是否有读取和写入ia32 / amd64预取指令?我在指令集参考中没有看到任何内容。
某些系统支持prefetchw
写入指令
- nt1,nt2,nta时间变量中的一个是首选的读取与写入预取吗?
如果该行是由调用线程专用的,那么无论你如何使用该行,读取和写入都可以使用它。上面提到的prefetchw的好处是它将带来线并给你所有权,如果该线也被另一个核使用,可能需要一段时间。另一方面,提示级别与MESI状态正交,并且仅影响预取线存活多长时间。如果您在实际访问之前预取很长时间并且不希望在该持续时间内预取,或者在访问之前预取,并且不希望预取过多地破坏缓存,则这很重要。
- 任何想法是否有充分的理由在ia32 / amd64上使用NTA时态提示,而在ia64上使用T1?
只是猜测 - 也许较大的缓存和积极的内存BW更容易受到不良预取的影响,并且您希望通过非时态提示减少影响。考虑到你的预取器突然松动以获取任何可能的东西,你最终会被垃圾预取淹没,这会通过大量有用的缓存线。 NTA提示使他们互相侵占,其余的完好无损。
当然,这也可能只是一个错误,我无法确定,只有开发编译器的人,但它可能是有道理的上述原因。
答案 1 :(得分:0)
我在x86预取提示类型上找到的最好的资源是好文章What Every Programmer Should Know About Memory。
在大多数情况下,x86对读取和写入预取没有不同的指令。异常似乎是那些非时间对齐的异常,其中写操作可以绕过缓存,但据我所知,读取将始终被缓存。
为什么早期的代码所有者在某个架构上使用了一个提示而不是另一个提示,这将很难回溯。他们可能会假设该系列中的处理器有多少缓存可用,那里的二进制文件的典型工作集大小,长期控制流模式等等......并且没有人知道这些假设中有多少是备份好的推理或数据。从这里有限的背景来看,我认为你有理由采用对你现在正在开发的平台最有意义的方法,无论在其他平台上做了什么。当您考虑像this one这样的文章时尤其如此,这些文章并不是我所听到的唯一上下文,它确实很难通过软件预取获得任何性能提升。
是否还有更多详细信息,比如使用此代码时的典型缓存未命中率,或预计会有多少预取有用?