在比较BFS算法的两种不同实现时,了解perf详细信息

时间:2018-04-18 19:08:00

标签: algorithm x86 breadth-first-search perf

以下结果使用具有32个核心的计算服务器上的perf进行测量。我知道我的实现没有经过优化,但是我想要进行比较。据我所知,图算法往往具有较低的局部性,研究人员试图解决这个问题。

但是,我不清楚结果。过去的时间是误导。我的实现在大约10秒内通过一个大约4mm节点的图形运行,其余的时间在预处理之前。优化版本使用相同的输入并遍历大约10次,每次不到一秒,所以它实际上只是预处理时间。我不是想要实现同样的目标。只是理解为什么这可能基于perf。

我看到我的页面错误要高得多。我不能确定为什么会出现这种情况,因为注释(从我能说的)并没有指出我的代码中的任何特定部分......

__gnu_cxx::new_allocator<std::_List_node<int> >::construct<int, int const&>

这似乎是我处理图表本身,因为我为邻接列表创建链接列表。我认为这实际上可能会导致问题并且无论如何都想进行调查。我应该能够通过切换到锯齿状数组来改善页面错误(并希望性能)?

优化算法具有更高的最后一级缓存未命中率,我认为这可以解释具有低局部性的BFS /图算法的主要问题,但性能似乎不受此影响且未优化的显着更低。

然后有前/后端周期在比较两者时在性能问题方面似乎相反 - 我在前端更糟糕,优化在后端更糟。

我是否遗漏或不理解明显的东西?我认为在低位置方面会有一些明显的东西在查看perf时会有问题,但我对优化版本感到困惑。

这是我对未经优化的并行BFS(运行一次)的实现......

My implementation of BFS

这是使用基准套件中优化的并行BFS(运行10次)......

enter image description here

在进行并行搜索之前,两次大约需要40秒才能预处理数据。

1 个答案:

答案 0 :(得分:2)

不幸的是,perf stat通常没有提供足够的信息来确定应用程序瓶颈的位置。可能有两个具有截然不同的底层瓶颈的应用程序,但具有非常相似的perf stat配置文件。例如,两个应用程序可能具有相同数量或分数的L2缓存未命中,但其中一个可能受此影响支配,而另一种方式可能几乎不受影响,具体取决于重叠工作的数量和性质。

因此,如果您尝试从这些高级计数器进行深入分析,您通常只是在黑暗中进行刺伤。我们仍然可以做一些观察。你提到:

  

优化算法具有更高的最后一级缓存未命中率   我认为可以解释BFS /图算法的主要问题   地点低但性能似乎不受此影响   我的未优化程度明显较低。

首先,对于优化算法,LLC未命中约为6.2亿,对于您的算法约为380,但您在此基准测试中运行优化算法10次且仅运行一次。因此,优化的算法可能有6200万个未命中,并且您的算法未命中数的六倍。是的,您的算法具有较低的LLC 未命中率 - 但LLC未命中的绝对数量是性能的重要因素。较低的未命中率意味着您进行的总访问次数超过6倍数:基本上您比优化版本进行了更多,更多的内存访问,从而导致更高的命中率但更多的总失误。

所有这些都指向在未经优化的算法中访问更多的总内存,或者以更加缓存不友好的方式访问它。这也可以解释更多的页面错误。总的来说,两种算法都具有较低的IPC,而你的算法特别低(0.49 IPC),并且鉴于没有分支预测问题,并且您已经将这些算法识别为具有位置/内存访问问题的图算法,很可能在等待记忆时失速。

幸运的是,有一种更好的方法可以尝试对基于perf stat输出的瓶颈进行逆向工程。英特尔开发了一种whole methodology,它以一种确定真正瓶颈的方式尝试这种自上而下的分析。它并不完美,但它比看普通的perf stat计数器要好得多。 VTune是免费的,但您可以使用Andi Kleen toplev基于相同的方法效果进行类似的分析。我强烈建议你从那里开始。