2016-08-23 13 views
-1

次のコードは、OpenMPを使用したリストランキングアルゴリズムの実装を示しています。このコードをプラグマなしで実行すると正しい結果が得られますが、プラグマをインクルードするとエラーが発生することがあります。出力は下部に表示されます。 2回目の出力が間違っていることがわかります。これはランダムに発生します。 プラグマを削除すると、私の出力は常に正しいです。プラグマを使用する方法にエラーがありますか、または私が紛失している依存関係がありますか? (順次出力される期待出力パラレル出力は、連続出力プログラムプリントDATA OK一致した場合。)OpenMPを使用したCのリストランキング実装 - 出力エラー

長さとスレッドの数である16

#define NSIZE 1 
#define NMAX 16 
int Ns[NSIZE] = {16}; 
int A[NMAX] = {14,13,5,16,11,10,9,12,0,8,7,15,4,3,2,1}; 
int B[NMAX + 1] = {0}; 

int S[NMAX + 1] = {0}; 

int Rp[NMAX + 1] = {0}; 
int next[NMAX+1] = {0}; 

for(int i = 1, j=0; i <= n; i++, j++) 
{ 
    B[i] = A[j]; 

} 

int chunk = ceil(length/nthreads); 
int i, j; 
int tid; 
//#pragma omp parallel num_threads(nthreads) 
//{ 
//#pragma omp for schedule(dynamic, chunk) private(i) 
for(i = 1; i <= length; i++) 
{ 

    Rp[i] = 1; 
    next[i] = S[i]; 
} 


for(i = 1; i<=log2(length); i++) 
{ 
#pragma omp parallel num_threads(nthreads) shared(Rp,next,chunk) private(j) 
{ 
    #pragma omp for schedule(dynamic,chunk) 
    for(j = 1; j <= length; j++) 
    { 
     if(next[j]!=0) 
     { 
      Rp[j] = Rp[j] + Rp[next[j]]; 

      next[j] = next[next[j]]; 
     } 
    } 

} 
} 

OUTPUT:

./をa.outの - OK
Inpuパラレル
データから

(私はプログラムを最初に実行したときにこれが出力されました) t:14 13 5 16 11 10 9 12 0 8 7 15 4 3 2 1
シーケンシャル:6 10 4 8 3 15 1 13 0 14 2 12 9 5 11 7
パラレル:6 10 4 8 3 15 1 13 0 14 2 12 9 5 11 7

./a.out - (私はプログラムをもう一度実行した出力時)
パラレルデータ不一致から!
入力:14 13 5 16 11 10 9 12 0 8 7 15 4 3 2 1
シーケンシャル:6 10 4 8 3 15 1 13 0 14 2 12 9 5 11 7
パラレル:6 10 4 8 3 15 1 13 0 10 2 12 9 5 11 7

./a.out - (私はプログラムを三度目を実行した出力)

パラレル
データからOK
入力:14 13 5 16 11 10 9 12 0 8 7 15 4 3 2 1
シーケンシャル:6 10 4 8 3 15 1 13 0 14 2 12 9 5 11 7
パラレル:6 10 4 8 3 15 1 13 0 14 2 12 9 5 11 7

+1

実際の[mcve]を含めるように質問してください。 'Rp'、' next'、 'S'はどこに定義されていますか?実際のエラーや予期しない出力は何ですか? (実際の出力と期待される出力を含めてください) –

+0

競合条件は次のとおりです: 'next [j] = next [next [j]];'。実際には、これは 'j'ループを移動する順番によって決まります。並列化しようとすると順序が変わり、結果を変更する可能性があります。 – Gilles

+0

@Gilles返事をありがとう。私はクリティカルな領域にifループを置くことで競合状態を解消しました。しかし、これは、現在、効率的にアルゴリズムをシーケンシャルに実行していることを意味します。レースを取り除くことができる他の方法はありますか(私はアルゴリズムを変更したくありません)。 – kumar

答えて

0

これは、2番目の配列セットでは可能であると思います。 私が間違っている場合は私を修正してください。

あなたは二つの配列と二つのポインタnext_newnext_oldと二つの配列と二つのポインタRp_newRp_oldを取るとき、それはトリックを行う必要があります。

古いから読み込み、各ラウンドの後にポインタを交換しながら、あなたは、新しい配列に書き込みます。

Rp_new[j] = Rp_old[j] + Rp_old[next_old[j]]; 

next_new[j] = next_old[next_old[j]]; 
関連する問題