visual-studio-2012 - 为什么在这个例子中预取加速不是更大?

标签 visual-studio-2012 intel sse

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

但是为什么预取在这里只帮助 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% 的加速。为什么预取对于随机访问主内存中的数据不起作用?

最佳答案

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

如果您的代码在从链表中的下一个节点请求数据之前花费了许多计算周期,它不会使内存保持 100% 忙碌。知道地址后立即预取下一个节点会有所帮助,但仍然存在上限。上限大约是您在没有预取的情况下获得的上限,但在加载节点和追逐指向下一个节点的指针之间没有任何工作。即内存系统在 100% 的时间内获取结果。

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

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

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

仅当 CPU 硬件预取器无法识别访问模式时才需要软件预取。 (它们非常好,并且可以以合适的步幅发现模式。并跟踪类似 10 个前向流(增加地址)的内容。查看 http://agner.org/optimize/ 了解详细信息。)

关于visual-studio-2012 - 为什么在这个例子中预取加速不是更大?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23741246/

相关文章:

c++ - 排序程序只显示第一个和最后一个数字

performance - 在大多数现代 64 位处理器上, `mulq` 的速度是否取决于操作数?

c - 如何加速以下代码以显着计算 CPU 上的 LBP?

linux - 如何找到在 Linux 上构建 mpi 基准测试所需的英特尔编译器目录的路径?

c - 如何访问 256 位 ps vector 的组件

x86 - 使用内在的未处理异常

c# - 如何先创建 EntityFramework 代码的可视化模型

c++ - 将 Visual C++ 控制台输出写入或复制到文本文件

c# - 使用自己的应用程序打开自定义文件

c - 处理器和协处理器之间的加密区别