【问题标题】:OMP parallel for reductionOMP 并行减少
【发布时间】:2015-02-09 21:50:22
【问题描述】:

我正在尝试编写一个 k-means 聚类类。我想让我的函数并行。

void kMeans::findNearestCluster()
{   
    short closest;
    int moves = 0;
    #pragma omp parallel for reduction(+:moves)
    for(int i = 0; i < n; i++)
    {      
        float min_dist=FLT_MAX;
        for(int k=0; k < clusters; k++)
        {
            float dist_sum = 0.0, dist2 = 0.0;
            for(int j = 0; j < dim; j++)
            {
                dist_sum = centroids[k*dim+j] - data[i*dim+j];
                dist2 +=  dist_sum * dist_sum;

            }
            if (dist2 < min_dist)
            {
                min_dist = dist2;
                closest = k;

            }

        }

        if (assignment[i] != closest)
        {
            assignment[i] = closest;
            moves++;
        }        

    }

    this->moves = moves;

}

它应该是这样工作的:

  • 第 1 步:找到最近的集群

    • 遍历所有数据点,并比较所有质心之间的距离。

    • 当找到最近的质心时,将其存储在名为closest的变量中。

    • 检查该点是否分配给新发现的最近的集群。如果没有,请将其移至新的。 (增量移动)

  • 第 2 步:根据新分配重新计算质心。 (功能未显示)

  • 重复第 1 步和第 2 步,直到不再发生移动。

没有#parallel moves 收敛到零。如果我有#parallel,则移动具有随机值。我认为是因为并行循环有冲突更新move

也许更好的策略是让每个线程都有自己的移动变量,最后它们会增加一些。

【问题讨论】:

    标签: c++ cluster-analysis openmp


    【解决方案1】:

    您在并行循环中使用closest 变量,在增加moves 变量之前将其写入并用作检查。但是它是在循环之外声明的,所以所有的迭代都使用同一个变量!由于所有迭代(理论上)都是并行执行的,因此您不能期望任何迭代都能看到任何其他迭代在分支条件if (assignment[i] != closest) 中写入closest 的内容。这个变量通过并行线程随机更新。因此,您的 moves 评估为垃圾值。

    closest 的声明移到外循环内或在OpenMP pragma 中将其声明为private(closest) 可能会解决您的问题。

    顺便说一句,closest 可能是未初始化的,最好和k 同类型,即int

    【讨论】:

      猜你喜欢
      • 2010-11-29
      • 2021-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-01
      相关资源
      最近更新 更多