2010-02-02 106 views
3

我有一個使用OpenMP來並行化for-loop的程序。在循環內部,線程將寫入共享變量,所以我需要同步它們。但是,我有時可能會遇到段錯誤或雙重釋放或損壞錯誤。有人知道會發生什麼?感謝致敬!下面是代碼:濫用OpenMP?

void KNNClassifier::classify_various_k(int dim, double *feature, int label, int *ks, double * errors, int nb_ks, int k_max) { 
    ANNpoint  queryPt = 0;  
    ANNidxArray nnIdx = 0;  
    ANNdistArray dists = 0;  

    queryPt = feature;  
    nnIdx = new ANNidx[k_max];     
    dists = new ANNdist[k_max];    

    if(strcmp(_search_neighbors, "brutal") == 0) {// search 
    _search_struct->annkSearch(queryPt, k_max, nnIdx, dists, _eps); 
    }else if(strcmp(_search_neighbors, "kdtree") == 0) { 
    _search_struct->annkSearch(queryPt, k_max, nnIdx, dists, _eps); // double free or corruption 
    } 

    for (int j = 0; j < nb_ks; j++) 
    { 
    scalar_t result = 0.0; 
    for (int i = 0; i < ks[j]; i++) {   
     result+=_labels[ nnIdx[i] ]; // Segmentation fault 
    } 
    if (result*label<0) 
    { 
    #pragma omp critical 
    { 
     errors[j]++; 
    } 
    } 

    } 

    delete [] nnIdx; 
    delete [] dists; 

} 

     void KNNClassifier::tune_complexity(int nb_examples, int dim, double **features, int *labels, int fold, char *method, int nb_examples_test, double **features_test, int *labels_test) {  
      int nb_try = (_k_max - _k_min)/scalar_t(_k_step);  
      scalar_t *error_validation = new scalar_t [nb_try];  
      int *ks = new int [nb_try];  

      for(int i=0; i < nb_try; i ++){  
      ks[i] = _k_min + _k_step * i;  
      }  

      if (strcmp(method, "ct")==0)                              
      {  

      train(nb_examples, dim, features, labels);// train once for all nb of nbs in ks                         

      for(int i=0; i < nb_try; i ++){  
       if (ks[i] > nb_examples){nb_try=i; break;}  
       error_validation[i] = 0;  
      }  

      int i = 0;  
     #pragma omp parallel shared(nb_examples_test, error_validation,features_test, labels_test, nb_try, ks) private(i)  
      {  
     #pragma omp for schedule(dynamic) nowait  
       for (i=0; i < nb_examples_test; i++)   
       {  
       classify_various_k(dim, features_test[i], labels_test[i], ks, error_validation, nb_try, ks[nb_try - 1]); // where error occurs  
       }  
      }  
      for (i=0; i < nb_try; i++)  
      {  
       error_validation[i]/=nb_examples_test;  
      }  
      } 

      ...... 
    } 

UPDATE:

正如我過去後double free or corruption,代碼運行正常用單線程,但給出了多線程運行時錯誤。該錯誤隨時發生變化。如果我運行兩次,其中一次將會出現段錯誤,另一次將會出現雙倍的空閒或腐敗現象。

+0

在段錯誤之前,i和nnIdx [i]的值是什麼? – 2010-02-02 07:09:36

+0

我是6. nnIdx [i]是1708204069,這是非常錯誤的,超出了可以被認爲合理的方式。不知道爲什麼。將值分配給nnIdx的元素的函數屬於ANN,庫爲 近似最近鄰搜索,請參閱http://www.cs.umd.edu/~mount/ANN/ – Tim 2010-02-02 07:32:40

回答

4

讓我們來看看你的分割斷層線:

result+=_labels[ nnIdx[i] ]; 

result是本地的 - 確定。

nnIdx是本地 - 也行。

i是本地 - 仍然可以。

_labels ...這是什麼?

它是全球性的嗎?你有沒有通過#pragma shared定義訪問權限?

也是一樣的前者:

_search_struct->annkSearch(queryPt, k_max, nnIdx, dists, _eps); 

似乎我們這裏有一個問題,是不是容易解決 - _search_struct不是線程安全的 - 大概值它是由線程同時修改。你必須有一個專用的_search_struct每線程,可能是通過在classify_various_k中分配它。

的真正的壞消息卻是,ANN可能是完全無螺:

庫分配少量的存儲量 ,這是通過在 程序的內置所有 搜索struc-功能共享一生。因爲共享數據 ,所以在刪除所有單個結構 時,不會釋放它,甚至不會釋放 。

如上所述,並行數據修改總會有問題,因爲庫本身有一些共享數據 - 因此它本身不是線程安全的:/。

+0

_labels是類KNNClassifier的數據成員。它並沒有明確宣佈爲共享敵人openmp。此外,如果我運行我的progrom兩次,一個將seg段,ang其他將是雙重免費或腐敗,如在我上一篇文章。即錯誤不是固定的。 – Tim 2010-02-02 07:08:23

+0

_search_struct-> annkSearch(queryPt,k_max,nnIdx,dists,_eps)用於在* _search_struct的k-d樹中組織的某些點中查找查詢點*特徵的k_max最近鄰點。 k-n鄰居的索引存儲在nnIdx中,並且它們與查詢點的距離爲dists。 – Tim 2010-02-02 07:18:19

+0

@Tim,更新了答案。 – 2010-02-02 08:29:45