2011-12-06 24 views
1

openmp forループの中でmalloc呼び出しを移動しようとすると、segフォルトに関する問題が発生します。各スレッドは、ベクトルをプライベートにする必要があるように、クラスを正確に計算するために、距離ベクトルの独自のコピーを計算しなければなりません...しかし、1スレッド以上で呼び出そうとすると、エラーが発生します。これは、p_distancesベクトルが共有として宣言されている場合には発生しませんが、もちろん、スレッドが互いに上書きするため、距離計算が不正確になります。私がここで違反している非常に明白なルールがありますか...また、私のコードには他の悪いコーディング方法があることを知っています。私はいつもスタイルに関する提案をしていますが、実際に問題を引き起こしているものに焦点を当ててください。PrivateMalloc用のOpenMP Segフォールト

int *labels_train; 
float *data_train; 
int *labels_test; 
float *data_test; 
float *s_distances; 
int *s_results, *p_results; 
int i, j, k, h; 
int N, D, K, M, thread_count; 

void sort(float *_distances, int *_labels_train, int _N); 

void computeParallelKNN() 
{ 
// this is the target loop for multi-point parallelization 
// seg fault here whenever p_distances malloc is moved inside parallel for loop and declared private 
#pragma omp parallel for num_threads(thread_count) private(h, j, i) 
for (i = 0; i < M; i++) 
{ 
    float *p_distances = (float*)malloc(N * sizeof(float)); 
    k = 0; 

    // This is the target loop for single point parallelization 
    // No dependencies on outer loop (each thread can calculate distance for current point with some 
    // different training point) 
    for (h = 0; h < N*D; h+=D) 
    { 
     float dTmp = 0; 
     // Reduction operation..no dependencies here either (I don't think?) 
     // dTmp is critical variable for parallel operations 
     for (j = 0; j < D; j++) 
     { 
      dTmp += pow(data_test[i*D+j] - data_train[h+j],2); 
     } 
     p_distances[k] = (float)sqrt((double)dTmp); 
     k++; 
    } 

    // Make a copy of labels (since sort will invalidate original data/labels correlation) 
    int *temp_labels; 
    temp_labels = (int*)malloc(N * sizeof(int)); 
    for (h = 0; h < N; h++) 
     temp_labels[h] = labels_train[h]; 

    // Sort distances/labels_train vector 
    sort(p_distances, temp_labels, N); 

    // Calculate/print KNN classification 
    int neg = 0; 
    int pos = 0; 
    for (h = 0; h < K; h++) 
    { 
     if(temp_labels[h] == -1) neg++; 
     else pos++; 
    } 
    if (pos > neg) p_results[i] = 1; 
    else p_results[i] = -1; 

    free(p_distances); 
     } 
} 

// Selection sort algorithm modified to sort labels according to distance data 
void sort(float *_distances, int *_labels_train, int _N) 
{ 
    int k; 
    for (k = 1; k < _N; ++k) 
    { 
    float dist_key = _distances[k]; 
    int label_key = _labels_train[k]; 
    int i = k - 1; 
    while ((i >= 0) && (dist_key < _distances[i])) 
    { 
     _distances[i + 1] = _distances[i]; 
     _labels_train[i + 1] = _labels_train[i]; 
     --i; 
    } 
    _distances[i + 1] = dist_key; 
    _labels_train[i + 1] = label_key; 
} 

}

私は完全なコードを投稿することができますが、これは間違いなく、障害が発生している地域です。前もってありがとう、うまくいけば、それはちょうど私が作っているばかげたミスです。

+0

:たとえば、

int i; void foo() { #pragma parallel private(i) { // ... } 

が同じである

。しかし、ループ外でp_distanceを宣言して、スレッドごとに次のように割り当ててみましたか?#pragma omp parallel private(p_distance、i、j、kなど)\ n {p_distance = calloc(N、sizeof(float )); \ n#(\ n {for(i = 0; i Bort

答えて

2

まず、すべてのスレッドで共有されるkがあります。その周りのクリティカルなセクションを知らせる宣言や、それを原子的に行うべきであるという宣言はありません。

コードをよりクリーンな方法で書き直し、できるだけグローバル変数を避けてください。新しいスコープを入力したばかりの変数を定義することができます。私はあなたのコードが動作しない理由は100%を確認していない

void foo() { 
#pragma parallel 
{ 
    int i; 
    // ... 
} 
関連する問題