OMPを使用して並列化すると異なる出力が得られるコードを添付します。 これは起こるつもりではありません。OMPスレッド数を増やすと出力値が変更されます
私は、通常の落とし穴を「私的な」変数と「削減」節に適用したと思います。
関連する機能をグローバルコードから添付します。どんな知恵にも感謝しています。
EDIT * MatIplusIplusのi番目の反復とMatPtJplusJplusのj番目の反復から取り出された列ベクトルのarma :: cross productに問題があると思われますか? *あなたはすべての行列に多くの競合状態を持っている
double calcul(arma::mat MatPt, int iS, int THREADS){
int i,j, count = 1;
double Wr = 0 , Omega;
arma::mat MatJplusIplus (3 , iS) ;
arma::mat MatJI (3 , iS) ;
arma::mat MatJplusI (3 , iS) ;
arma::mat MatJIplus (3 , iS) ;
arma::mat MatIplusI (3 , iS) ;
arma::mat MatJplusJ (3 , iS) ;
#pragma omp parallel for private(j) reduction(+: Wr) reduction(*: Omega)
for(i = 0 ; i < iS- (3) ; i++){//rethink boundaries.
MatIplusI (0 , i) = MatPt (0, i+1) - MatPt (0, i) ;
MatIplusI (1 , i) = MatPt (1, i+1) - MatPt (1, i) ;
MatIplusI (2 , i) = MatPt (2, i+1) - MatPt (2, i) ;
for(j= i+2 ; j < iS-(1) ; j++){
MatJIplus (0, j) = MatPt (0, j) - MatPt (0, i+1) ;
MatJIplus (1, j) = MatPt (1, j) - MatPt (1, i+1) ;
MatJIplus (2, j) = MatPt (2, j) - MatPt (2, i+1) ;
MatJplusIplus (0, j) = MatPt (0, j+1) - MatPt (0, i+1) ;
MatJplusIplus (1, j) = MatPt (1, j+1) - MatPt (1, i+1) ;
MatJplusIplus (2, j) = MatPt (2, j+1) - MatPt (2, i+1) ;
MatJI (0, j) = MatPt (0, j) - MatPt (0, i) ;
MatJI (1, j) = MatPt (1, j) - MatPt (1, i) ;
MatJI (2, j) = MatPt (2, j) - MatPt (2, i) ;
MatJplusI (0, j) = MatPt (0, j+1) - MatPt (0, i) ;
MatJplusI (1, j) = MatPt (1, j+1) - MatPt (1, i) ;
MatJplusI (2, j) = MatPt (2, j+1) - MatPt (2, i) ;
arma::vec n1 = arma::cross(MatJI.col(j) , MatJplusI.col(j)) ;
arma::vec n2 = arma::cross(MatJplusI.col(j) , MatJplusIplus.col(j)) ;
arma::vec n3 = arma::cross(MatJplusIplus.col(j) , MatJIplus.col(j)) ;
arma::vec n4 = arma::cross(MatJIplus.col(j) , MatJI.col(j)) ;
//normalise vectors
arma::vec N1 = normalise(n1) ;
arma::vec N2 = normalise(n2) ;
arma::vec N3 = normalise(n3) ;
arma::vec N4 = normalise(n4) ;
//take dot product
const double ndot1 = arma:: dot (N1 , N2) ;
const double ndot2 = arma:: dot (N2 , N3) ;
const double ndot3 = arma:: dot (N3 , N4) ;
const double ndot4 = arma:: dot (N4 , N1) ;
Omega = asin(ndot1) + asin(ndot2) + asin(ndot3) + asin(ndot4) ;
MatJplusJ(0 , j) = MatPt (0, j+1) - MatPt (0, j) ;
MatJplusJ (1 , j) = MatPt (1, j+1) - MatPt (1, j) ;
MatJplusJ (2 , j) = MatPt (2, j+1) - MatPt (2, j) ;
arma::vec v = arma::cross(MatJplusJ.col(j) , MatIplusI.col(i));
const double wij = arma:: dot(v, MatJI.col(j)) ;
if (wij < 0){
Omega *= -1/ (4* pi) ;
}
else{
Omega *= 1/ (4* pi) ;
}
if (Omega != Omega){//incase something goes wrong, ignore !
Omega = 0 ;
}
Wr += Omega ;
//cout << i << " " << j << endl ;
//PrivEnd
}
}
Wr *= 2 ;
return Wr ;
}
感謝
パラレルセクションの後に 'Omega'を使用しないと、どのような削減が行われますか?あなたが望むのは 'private(Omega)'です – simpel01
スレッドの数によって結果が変わると、データ競合のようなにおいがします。 –
オメガはプライベートに設定されています(感謝simple01!) –