首页 文章

OMP并行减少

提问于
浏览
0

我正在尝试编写一个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;

}

这是它应该如何工作:

  • Step 1 :查找最近的群集

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

  • 找到最近的质心时,它存储在名为 closest 的变量中 .

  • 检查此点是否已分配给新找到的最近的群集 . 如果没有,请移动新的 . (增量动作)

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

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

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

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

1 回答

  • 1

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

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

    顺便说一句, closest 可能是未初始化的,并且应该与 k 的类型相同,即 int .

相关问题