【发布时间】:2014-07-07 14:52:42
【问题描述】:
在this excellent paperUlrich Drepper 的 6.3.2 中,写了关于软件预取的文章。他说这是“熟悉的指针追踪框架”,我收集的是他之前给出的关于遍历随机指针的测试。在他的图表中,当工作集超过缓存大小时性能下降是有道理的,因为那时我们将越来越频繁地使用主内存。
但是为什么预取在这里只有 8% 的帮助呢?如果我们准确地告诉处理器我们想要加载什么,并且我们提前告诉它足够远(他提前 160 个周期),为什么缓存不能满足每个访问?他没有提到他的节点大小,所以当只需要一些数据时,可能会因为获取一整行而造成一些浪费?
我正在尝试将 _mm_prefetch 与一棵树一起使用,但我没有看到明显的加速。我正在做这样的事情:
_mm_prefetch((const char *)pNode->m_pLeft, _MM_HINT_T0);
// do some work
traverse(pNode->m_pLeft);
traverse(pNode->m_pRight)
现在这应该只有助于一侧的遍历,但我认为性能没有任何变化。我确实将 /arch:SSE 添加到项目设置中。我正在使用带有 i7 4770 的 Visual Studio 2012。在this thread 中,一些人还谈到预取仅能获得 1% 的加速。为什么预取对随机访问主存中的数据不起作用?
【问题讨论】:
-
在现代 CPU 上很难击败自动预取,除非 (a) 您有不寻常/可预测的访问模式,(b) 您真的知道自己在做什么, (c) 您已准备好针对特定 CPU 进行调整,并且 (d) 您有可用的内存带宽。
-
嗯,但是图表呢?如果他准确地告诉处理器他接下来要读取什么地址,他如何仍然获得 1000 个周期/元素?似乎在稳定状态下,无论工作集大小如何,他都应该回落到 200 个周期/节点以下。当他在每个节点上进行工作时,所有的获取都应该发生。我知道我的心智模型一定遗漏了很多,只是不确定是什么。
-
@Philip 不,因为随着您的数据集变大,您将从主内存中预取,缓存命中次数会减少很多。小型工作集可能完全驻留在缓存中。
-
@Anycom,对,但预取的整个想法是在需要之前从主内存启动传输。在他的示例中,他在每个节点上执行 160 个工作周期。不是 200 个周期的数量级的主存储器获取吗?那么,如果您在需要 160 个周期之前启动 200 个周期,为什么需要 1000 个周期呢? paul-r 和 Ulrich 报告的内容与我的经验一致,没有太大帮助,但似乎应该有很大帮助。
-
@Philip 这不仅仅是原始内存延迟,例如 TLB 未命中非常昂贵。
标签: visual-studio-2012 intel sse