[英]OpenMP/C++: Parallel for loop with reduction afterwards - best practice?
[英]openmp parallel loop reduction of double *
我在使用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)
必須糾正,但我不知道該怎么做。
您在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] ;
那么它是每個線程專用的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.