我尝试使用OpenMP优化以下循环:
#pragma omp parallel for private(diff)
for (int j = 0; j < x.d; ++j) {
diff = x(example,j) - x(chosen_pts[ndx - 1],j);
#pragma omp atomic
d2 += diff * diff;
}
但它实际上比没有#pragma
慢了4倍。
修改
正如Piotr S.,coincoin和erenon指出的那样,在我的情况下x.d
是如此之小,这就是为什么并行性使我的代码运行得慢。我也发布了外循环,也许有多线程的可能性:( x.n超过1亿)
float sum_distribution = 0.0;
// look for the point that is furthest from any center
float max_dist = 0.0;
for (int i = 0; i < x.n; ++i) {
int example = dist2[i].second;
float d2 = 0.0, diff;
//#pragma omp parallel for private(diff) reduction(+:d2)
for (int j = 0; j < x.d; ++j) {
diff = x(example,j) - x(chosen_pts[ndx - 1],j);
d2 += diff * diff;
}
if (d2 < dist2[i].first) {
dist2[i].first = d2;
}
if (dist2[i].first > max_dist) {
max_dist = dist2[i].first;
}
sum_distribution += dist2[i].first;
}
如果有人感兴趣,这是整个功能:https://github.com/ghamerly/baylorml/blob/master/fast_kmeans/general_functions.cpp#L169,但是我测量了85%的经过时间来自此循环。
答案 0 :(得分:1)
是的,发布的外部循环可以与OpenMP并行化。
循环中修改的所有变量都是迭代的本地变量,或者用于循环聚合。我假设在计算x()
时调用diff
没有副作用。
要正确有效地并行进行聚合,您需要使用带有reduction
子句的OpenMP循环。对于sum_distribution
,缩减操作为+
,而max_dist
缩放操作为max
。因此,在外部循环前面添加以下编译指示应该可以完成这项工作:
#pragma omp parallel for reduction(+:sum_distribution) reduction(max:max_dist)
请注意,max
作为缩减操作只能在OpenMP 3.1之后使用。它并不是那么新,所以大多数支持OpenMP的编译器已经支持它,但不是全部;或者您可以使用旧版本。因此,咨询编译器的文档是有意义的。