【发布时间】:2015-05-26 00:46:47
【问题描述】:
我正在编写一个程序来分析社交网络图。这意味着程序需要大量的随机内存访问。在我看来,预取应该有所帮助。这是从顶点的邻居读取值的一小段代码。
for (size_t i = 0; i < v.get_num_edges(); i++) {
unsigned int id = v.neighbors[i];
res += neigh_vals[id];
}
我将上面的代码转换为下面的代码,并预取一个顶点的邻居的值。
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];
}
}
在这个 C++ 代码中,我没有重写任何运算符。
不幸的是,代码并没有真正提高性能。我想知道为什么。显然,硬件预取在这种情况下不起作用,因为硬件无法预测内存位置。
我想知道这是否是由 GCC 优化引起的。当我编译代码时,我启用 -O3。我真的希望即使启用了-O3,预取也能进一步提高性能。在这种情况下 -O3 优化是否融合了两个循环?这种情况下-O3可以默认开启预取吗?
我使用 gcc 版本 4.6.3,程序在 Intel Xeon E5-4620 上运行。
谢谢, 大
【问题讨论】:
-
get_neighbor在做什么?neigh_vals的类型是什么?vertex_id_t是什么?v是什么?请编辑您的问题以改进它。 -
另见this answer 相关问题
-
看起来您在一个循环中预取并希望数据在下一个循环中仍然可用。这不太可能有帮助,而且可能会造成伤害。
-
gcc的哪个版本,哪个处理器?您需要编辑您的问题以改进它。 -
旁白:
v.get_num_edges()在整个for循环中是不变的吗?看起来您可以将它分配给一个变量,而不是每次通过循环顶部调用它。
标签: c performance gcc prefetch