A PRIVATE variable should not be modified inside a MASTER region.
This pattern of usage usually indicates an error or a misguided use of OpenMP*. The MASTER directive marks a block that is only executed by the master thread; all other threads in a parallel region bypass a master block. The PRIVATE clause designates a variable that is replicated on a per-thread basis on entry to a parallel region.
There are two possibilities. The first is that the value written by the master thread does not affect any statements outside the MASTER region. If this is true, then there is no reason to designate this variable as PRIVATE. After all, PRIVATE variables are replicated for every thread. If that variable is only used by the master thread, then create a copy for the other threads? The other possibility is that the value written by the master thread does affect statements outside the MASTER region. In that case, the statements outside the MASTER region behave differently when they are executed by the master thread than they do when executed by another thread. This violates the basic principle that every OpenMP program should produce the same results when run in parallel and serial mode. Therefore, this usage is either incorrect or inefficient.
ID |
Observation |
Description |
---|---|---|
1 |
OpenMP usage error |
The place the variable was assigned |
2 |
OpenMP declaration |
The location of the MASTER directive |
// Example adapted from A.15.1c from OpenMP 3.0 Specification // Copyright (C) 1997-2008 OpenMP Architecture Review Board // Here the master thread keeps track of how many iterations // have been executed and prints out a progress report. // This example has been modified to add a private clause // on the first #pragma. This is an unnecessary inefficiency, // because the use of the master region implies that c is // not used by other threads. Therefore the other threads do not // need to have their own copies created by the PRIVATE clause. #include <stdio> extern float average(float,float,float); void a15( float* x, float* xold, int n, float tol ) { int c, i, toobig; float error, y; c = 0; #pragma omp parallel private(c) // bad: c should not be private { do { #pragma omp for private(i) for( i = 1; i < n-1; ++i ) { xold[i] = x[i]; } #pragma omp single { toobig = 0; } #pragma omp for private(i,y,error) reduction(+:toobig) for( i = 1; i < n-1; ++i ) { y = x[i]; x[i] = average( xold[i-1], x[i], xold[i+1] ); error = y - x[i]; if( error > tol || error < -tol ) ++toobig; } #pragma omp master { ++c; // c used in master region printf( "iteration %d, toobig=%d\n", c, toobig ); } } while( toobig > 0 ); } }
Copyright © 1997-2008 OpenMP Architecture Review Board.
Permission to copy without fee all or part of this material is granted, provided the OpenMP Architecture Review Board copyright notice and the title of this document appear. Notice is given that copying is by permission of OpenMP Architecture Review Board.
Copyright © 2010, Intel Corporation. All rights reserved.