我正在编写一个分析社交网络图的程序。这意味着程序需要大量的随机内存访问。我认为预取应该会有所帮助。下面是从一个顶点的邻居读取数值的代码示例。
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 上运行程序。
谢谢, Da
v.get_num_edges()
是否不变?看起来你可以将其赋值给一个变量,而不是每次通过循环顶部调用它。 - Andy Lester