我附加了一个代码,当使用OMP进行并行化时会产生不同的输出。 这并不意味着发生。
我相信我已经涵盖了与'私人'变量和'减少'条款相关的通常常见的陷阱。
我附加了全局代码中的相关函数。感激地接受任何智慧。
编辑*我怀疑问题出在我的arma :: cross乘以从MatIplusIplus的第i次迭代和MatPtJplusJplus的第j次迭代中得到的列向量? *
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 ;
}
非常感谢
答案 0 :(得分:0)
j
上的所有矩阵访问都有很多竞争条件。例如,MatJIplus ( 0, j ) = ...
将由外部循环的不同迭代同时设置。
由于这些数据结构是间接的,因此您不能将它们声明为私有,您必须在工作线程本身中构造它们。由于您只使用在每个循环体内写入的矩阵部分,因此可以在循环体内声明它们。但是,为了避免在每个循环中反复重新分配这些,您可以将parallel for
拆分为:
arma::mat MatIplusI ( 3 , iS ) ;
#pragma omp parallel
{
// Matrices will be implicitly private and correctly constructed locally for each thread.
arma::mat MatJplusIplus ( 3 , iS ) ;
arma::mat MatJI ( 3 , iS ) ;
arma::mat MatJplusI ( 3 , iS ) ;
arma::mat MatJIplus ( 3 , iS ) ;
arma::mat MatJplusJ ( 3 , iS ) ;
#pragma omp parallel for private(j) reduction(+: Wr) private(Omega)
{
for( i = 0 ; i < iS- (3) ; i++ )
请注意,减少Omega
绝对没有意义,它应该是私有的。
当你在每次迭代中只使用它们的列时,为完整矩阵分配内存也没什么意义。只需创建一个合适的私有数据结构来保存column(i/j)
内容。