我在使用OpenMP进行数组(double **
)的减少(求和)时遇到问题。代码是:
#include <stdlib.h>
#include <iostream>
#include <omp.h>
using namespace std ;
double my_function(const double * x) { return 1 ; }
int main()
{
const int nb_mom_x = 5 ;
const int nb_mom_y = 5 ;
const int mesh_nb_pts_x = 1000 ;
const int mesh_nb_pts_y = 1000 ;
double PDF_moments[nb_mom_x][nb_mom_y] ;
double tmp_coordinates[2] ;
// Initialisation :
for ( int k_ordre_mom_x = 0 ; k_ordre_mom_x < nb_mom_x ; k_ordre_mom_x++ )
for( int k_ordre_mom_y = 0 ; k_ordre_mom_y < nb_mom_y ; k_ordre_mom_y++ )
PDF_moments[k_ordre_mom_x][k_ordre_mom_y] = 0.0 ;
#pragma omp parallel for reduction(+:PDF_moments)
for ( int k_mesh_x = 0 ; k_mesh_x < mesh_nb_pts_x ; k_mesh_x++ )
{
// Abscissa of the point in x:
tmp_coordinates[0] = (double) k_mesh_x/mesh_nb_pts_x ;
// Evaluation of the powers of x:
double tmp_pow_x[nb_mom_x] ;
tmp_pow_x[0] = 1.0 ;
for ( int k_ordre_mom_x = 1 ; k_ordre_mom_x < nb_mom_x ; k_ordre_mom_x++ )
tmp_pow_x[k_ordre_mom_x] = tmp_pow_x[k_ordre_mom_x-1] * tmp_coordinates[0] ;
for ( int k_mesh_y = 0 ; k_mesh_y < mesh_nb_pts_y ; k_mesh_y++ )
{
// Abscissa of the point in y:
tmp_coordinates[1] = (double) k_mesh_y/mesh_nb_pts_y ;
// Evaluation of the powers of y:
double tmp_pow_y[nb_mom_y] ;
tmp_pow_y[0] = 1.0 ;
for ( int k_ordre_mom_y = 1 ; k_ordre_mom_y < nb_mom_x ; k_ordre_mom_y++ )
tmp_pow_y[k_ordre_mom_y] = tmp_pow_y[k_ordre_mom_y-1] * tmp_coordinates[0] ;
// Evaluation of the function:
double tmp_function = my_function( tmp_coordinates ) ;
for( int k_ordre_mom_y = 0 ; k_ordre_mom_y < nb_mom_y ; k_ordre_mom_y++ )
for ( int k_ordre_mom_x = 0 ; k_ordre_mom_x < nb_mom_x ; k_ordre_mom_x++ )
PDF_moments[k_ordre_mom_x][k_ordre_mom_y] += tmp_function * tmp_pow_x[k_ordre_mom_x] * tmp_pow_y[k_ordre_mom_y] ;
}
}
for ( int k_ordre_mom_x = 0 ; k_ordre_mom_x < nb_mom_x ; k_ordre_mom_x++ )
for( int k_ordre_mom_y = 0 ; k_ordre_mom_y < nb_mom_y ; k_ordre_mom_y++ )
PDF_moments[k_ordre_mom_x][k_ordre_mom_y] *= (1.0/mesh_nb_pts_x)*(1.0/mesh_nb_pts_y) ;
// Display of the moments of the function:
printf("\n+-------+") ;
for ( int k_ordre_mom_y = 0 ; k_ordre_mom_y < nb_mom_y ; k_ordre_mom_y++ ) printf("------------+") ;
printf("\n| Ordre |") ;
for ( int k_ordre_mom_y = 0 ; k_ordre_mom_y < nb_mom_y ; k_ordre_mom_y++ ) printf(" % 9.1d |",k_ordre_mom_y) ;
printf("\n+-------+") ;
for ( int k_ordre_mom_y = 0 ; k_ordre_mom_y < nb_mom_y ; k_ordre_mom_y++ ) printf("------------+") ;
for ( int k_ordre_mom_x = 0 ; k_ordre_mom_x < nb_mom_x ; k_ordre_mom_x++ )
{
printf("\n| % 5.1d |",k_ordre_mom_x ) ;
for( int k_ordre_mom_y = 0 ; k_ordre_mom_y < nb_mom_y ; k_ordre_mom_y++ )
{
printf(" % 1.3e |" ,PDF_moments[k_ordre_mom_x][k_ordre_mom_y] ) ;
}
}
printf("\n+-------+") ;
for ( int k_ordre_mom_y = 0 ; k_ordre_mom_y < nb_mom_y ; k_ordre_mom_y++ ) printf("------------+") ;
printf("\n");
return 0 ;
}
当我在mac上使用g++-7 -fopenmp main.cpp -O0 -o out.exe
编译此代码时结果是错误的,问题如下。但是,如果我在编译此代码后对该行进行评论:#pragma omp parallel for reduction(+:PDF_moments)
,结果是正确的。
所以我的猜测是命令的选项:#pragma omp parallel for reduction(+:PDF_moments)
必须得到纠正,但我不知道该怎么做。
答案 0 :(得分:0)
tmp_coordinates
上有竞争条件。默认情况下,向量是共享的,因为它是在循环之外声明的,即使它对每个循环迭代都是独立的。相反,在循环中声明它:
#pragma omp parallel for reduction(+:PDF_moments)
for ( int k_mesh_x = 0 ; k_mesh_x < mesh_nb_pts_x ; k_mesh_x++ )
{
double tmp_coordinates[2] ;
然后它对每个线程都是私有的。