2015-02-09 42 views
0

我想寫一個k-means聚類類。我想讓我的功能平行。OMP並行減少

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,直到沒有更多移動發生。

沒有#parallelmoves收斂到零。如果我有#parallel移動具有隨機值。我認爲,因爲並行循環有衝突更新move

也許一個更好的策略是讓每個線程都有自己的移動變量,最後他們會有一些。

回答

1

您可以使用並行循環內的closest變量寫入並將其用作檢查,然後再增加變量moves。但它是在循環外部聲明的,所以所有迭代都使用相同的變量!由於所有迭代都是並行執行的(理論上),所以不能指望任何迭代都可以看到任何其他迭代在分支條件if (assignment[i] != closest)中寫入closest的情況。這個變量通過賽車並行線程被隨機更新。因此你的moves評估爲垃圾價值。

將外部循環內的closest聲明或在OpenMP編譯指示中聲明爲private(closest)可以解決您的問題。

順便說一下,closest可能未初始化,應該是k,即int相同的類型。