2017-05-19 6 views
0

私は少し苦労します。外部ループをOpenMPで最適化し、還元を

#pragma omp parallel reduction(+:det). 

私はそれを解決する方法と失敗した理由を誰かに教えてもらえますか?

// template<class T> using vector2D = std::vector<std::vector<T>>; 

float Det(vector2DF &a, int n) 
{ 
    vector2DF m(n - 1, vector1DF(n - 1, 0)); 

    if (n == 1) return a[0][0]; 
    if (n == 2) return a[0][0] * a[1][1] - a[1][0] * a[0][1]; 

    float det = 0; 
    for (int i = 0; i < n; i++) 
    { 
    int l = 0; 
#pragma omp parallel for private(l) 
    for (int j = 1; j < n; j++) 
    { 
     l = 0; 
     for (int k = 0; k < n; k++) 
     { 
     if (k == i) continue; 
     m[j - 1][l] = a[j][k]; 
     l++; 
     } 
    } 
    det += std::pow(-1.0, 1.0 + i + 1.0) * a[0][i] * Det(m, n - 1); 
    } 

    return det; 
} 
+1

_計算が間違っています。また、期待される出力は?実際の出力とは何ですか?あなた自身で問題を解決しようとするためにどのような措置を講じましたか? –

+0

これは元のバージョンです:/ https://pastebin.com/ZJFjAY5T – dgrat

+0

あなたの質問に答える(またはあなたの問題を解決する)ために必要なすべての情報は、質問自体に存在し、いくつかの外部リンクではなく、不特定の時間。そのために、私は外部のリンクに従うことを拒否します。 –

答えて

2

あなたが外側のループを並列化した場合、この行の競合状態があります:

m[j - 1][l] = a[j][k]; 

はまた、あなたは可能性が高いだけでなくparallel reductionparallel for reductionをしたいです。

mは、内部ループで完全に上書きされるため、必要ではないにしても、それは共有されています。常にローカルにできるだけ変数を宣言し、これは誤って共有変数、例えばの問題を回避:

float Det(vector2DF &a, int n) 
{ 
    if (n == 1) return a[0][0]; 
    if (n == 2) return a[0][0] * a[1][1] - a[1][0] * a[0][1]; 

    float det = 0; 
    #pragma omp parallel reduction(+:det) 
    for (int i = 0; i < n; i++) 
    { 
    vector2DF m(n - 1, vector1DF(n - 1, 0)); 
    for (int j = 1; j < n; j++) 
    { 
     int l = 0; 
     for (int k = 0; k < n; k++) 
     { 
     if (k == i) continue; 
     m[j - 1][l] = a[j][k]; 
     l++; 
     } 
    } 
    det += std::pow(-1.0, 1.0 + i + 1.0) * a[0][i] * Det(m, n - 1); 
    } 
    return det; 
} 

今では正しいのですが、mを割り当てることは高価なことができるので、パフォーマンスはそれぞれ、すべてでそれをやっていないから利益を得ることができます繰り返し。これは、次のようなparallelforディレクティブを分割することによって行うことができます。

float Det(vector2DF &a, int n) 
{ 
    if (n == 1) return a[0][0]; 
    if (n == 2) return a[0][0] * a[1][1] - a[1][0] * a[0][1]; 

    float det = 0; 
    #pragma omp parallel reduction(+:det) 
    { 
    vector2DF m(n - 1, vector1DF(n - 1, 0)); 
    #pragma omp parallel for 
    for (int i = 0; i < n; i++) 
    { 
     for (int j = 1; j < n; j++) 
     { 
     int l = 0; 
     for (int k = 0; k < n; k++) 
     { 
      if (k == i) continue; 
      m[j - 1][l] = a[j][k]; 
      l++; 
     } 
     } 
     det += std::pow(-1.0, 1.0 + i + 1.0) * a[0][i] * Det(m, n - 1); 
    } 
    } 
    return det; 
} 

今、あなたはまた、単にfirstprivateとしてmを宣言することができますが、それはコピーコンストラクタは完全に独立したディープコピーを作成することを前提とし、したがって、コードになるだろう推理するのが難しい

期待される出力、実際の出力、およびminimal complete and verifiable exampleを常に含めるようにしてください。