与omp平行

时间:2014-12-28 10:38:36

标签: c++ multithreading openmp

我尝试使用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%的经过时间来自此循环。

1 个答案:

答案 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的编译器已经支持它,但不是全部;或者您可以使用旧版本。因此,咨询编译器的文档是有意义的。