为什么GCC __builtin_prefetch没有提高性能?

Da *_*eng 2 c performance gcc prefetch

我正在编写一个程序来分析社交网络图.这意味着程序需要大量的随机内存访问.在我看来,预取应该有所帮助.这是从顶点的邻居读取值的一小段代码.

for (size_t i = 0; i < v.get_num_edges(); i++) {
    unsigned int id = v.neighbors[i];
    res += neigh_vals[id];
}
Run Code Online (Sandbox Code Playgroud)

我将上面的代码转换为下面的代码,并预取顶点的邻居值.

int *neigh_vals = new int[num_vertices];

for (size_t i = 0; i < v.get_num_edges(); i += 128) {
    size_t this_end = std::min(v.get_num_edges(), i + 128);
    for (size_t j = i; j < this_end; j++) {
        unsigned int id = v.neighbors[j];
        __builtin_prefetch(&neigh_vals[id], 0, 2);
    }
    for (size_t j = i; j < this_end; j++) {
        unsigned int id = v.neighbors[j];
        res += neigh_vals[id];
    }
}
Run Code Online (Sandbox Code Playgroud)

在这个C++代码中,我没有覆盖任何运算符.

不幸的是,代码并没有真正提高性能.我想知道为什么.显然,硬件预取在这种情况下不起作用,因为硬件无法预测内存位置.

我想知道它是否是由GCC优化引起的.当我编译代码时,我启用-O3.我真的希望即使启用-O3,预取也可以进一步提高性能.在这种情况下,-O3优化是否融合了两个循环?在这种情况下,-O3能否默认启用预取?

我使用gcc 4.6.3版,程序在Intel Xeon E5-4620上运行.

谢谢,Da

Bas*_*tch 7

是的,GCC的一些最新版本(例如2015年3月的4.9)能够PREFETCH在优化时发出一些指令-O3(即使没有任何明确的__builtin_prefetch)

我们不知道get_neighbor在做什么,以及什么类型的vneigh_val.

预取并不总是有利可图.添加显式__builtin_prefetch可能会降低代码速度.你需要衡量.

正如Retired Ninja评论的那样,在一个循环中进行预取并希望数据将在以下循环中缓存(在源代码中进一步向下)是错误的.

你也许可以尝试一下

for (size_t i = 0; i < v.get_num_edges(); i++) {
  fg::vertex_id_t id = v.get_neighbor(i);
  __builtin_prefetch (neigh_val[v.get_neighbor(i+4)]);
  res += neigh_vals[id];
}
Run Code Online (Sandbox Code Playgroud)

你可以凭经验替换4任何适当的常数是最好的.

但我猜__builtin_prefetch上面的内容是无用的(因为编译器可能会自己添加它)并且它可能会损害(甚至崩溃程序,当计算其参数给出未定义的行为时,例如,如果v.get_neighbor(i+4)未定义;但是在外部预取地址您的地址空间不会受到伤害 - 但可能会减慢您的程序速度).请基准.

查看相关问题的答案.

请注意,在C++中,所有的[],get_neighbor都可能被重载并变得非常复杂的操作,所以我们无法猜测!

并且有些情况下硬件会限制性能,无论__builtin_prefetch你添加什么(并添加它们都会损害性能)

顺便说一下,您可以通过-O3 -mtune=native -fdump-tree-ssa -S -fverbose-asm了解更多编译器正在做的事情(并查看生成的转储文件和汇编程序文件); 而且,确实会-O3产生稍微慢于代码的代码-O2.

如果你有时间浪费在优化上,你可以考虑显式多线程,OpenMP,OpenCL.请记住,过早优化是邪恶的.您是否进行了基准测试,是否对整个应用程序进

  • 需要明确的是,"甚至使程序崩溃"并不意味着如果地址无效,则预取会产生错误,但地址表达式本身必须有效. (3认同)