为什么在此示例中预取加速不会更大?

时间:2014-05-19 15:09:03

标签: visual-studio-2012 intel sse

在此this excellent paper的6.3.2中,Ulrich Drepper撰写了关于软件预取的文章。他说这是“熟悉的指针追逐框架”,我收集的是他之前给出的关于遍历随机指针的测试。在他的图表中,当工作集超过缓存大小时,性能会逐渐消失,因为那时我们会越来越频繁地访问主内存。

但为什么prefetch在这里仅提供8%的帮助?如果我们告诉处理器我们想要加载什么,并且我们提前告诉它足够远(他提前160个循环),为什么缓存不满足每个访问?他没有提到他的节点大小,所以当只需要一些数据时,由于获取一个完整的行可能会有一些浪费?

graph of prefetch improvement

我正在尝试将_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%的加速。为什么预取不会对主内存中的数据随机访问产生奇迹?

2 个答案:

答案 0 :(得分:2)

预取不能增加主内存的吞吐量,它只能帮助您更接近使用它。

如果您的代码在从链接列表中的下一个节点请求数据之前花费了很多计算周期,则不会使内存保持100%忙碌状态。一旦知道地址就预取下一个节点将有所帮助,但仍有一个上限。上限大约是你没有预取的结果,但在加载节点和追逐下一个指针之间没有工作。即内存系统100%的时间获取结果。

根据该论文中的图表,即使在160个工作周期之前进行预取也不足以使数据准备就绪。随机访问延迟显然非常慢,因为DRAM必须打开新页面,新行和新列。

我没有详细阅读本文,看看他如何预先提取多个步骤,或者理解为什么预取线程比预取指令更有帮助。这是在P4,而不是Core或Sandybridge微体系结构,我不认为预取线程仍然是一个东西。 (具有超线程的现代CPU具有足够的执行单元和足够大的高速缓存,在每个核心的两个硬件线程上运行两个独立的东西实际上是有意义的,不像在P4中,通常用于超线程以利用的额外执行资源较少。并且esp I-cache是​​P4中的一个问题,因为它只有那个小的跟踪缓存。)

如果你的代码已经基本上立即加载了下一个节点,那么预取不会神奇地使它更快。预取有助于增加CPU计算和等待内存之间的重叠。或者也许在你的测试中,->left指针大多是从你分配内存时开始的顺序,所以HW预取有效吗?如果树足够浅,则在向左下降之前预取->right节点(进入最后一级缓存,而不是L1)可能是一个胜利。

仅当CPU硬件预取程序无法识别访问模式时,才需要

软件预取。 (它们非常好,并且可以通过适当大小的步幅来发现模式。并跟踪10个前向流(增加地址)之类的内容。请查看http://agner.org/optimize/以获取详细信息。)

答案 1 :(得分:-1)

您想要预取的节点有多大?因为预取器不能超过4K页面边界:如果节点较大,则只预加载部分数据,而剩余数据仅在未命中事件后加载。