OpenMP: Data-Sharing Rules
A variable in an OpenMP parallel region can be either shared or private. If a variable is shared, then there exists one instance of this variable which is shared among all threads. If a variable is private, then each thread in a team of threads has its own local copy of the private variable.
In this article, we look how OpenMP specifies if a variable is shared or private.
Implicit Rules
OpenMP has a set of rules, which deduce the data-sharing attributes of variables.
For example, let us consider the following snippet of code.
There are four variables i
, n
,
a
and b
.
The data-sharing attribute of variables, which are declared outside the
parallel region, is usually shared. Therefore, n
and
a
are shared variables.
The loop iteration variables, however, are private by default. Therefore,
i
is private.
The variables which are declared locally within the parallel region are
private. Thus b
is private.
I recommend to declare the loop iteration variables inside the parallel region. In this case, it is clearer that this variables are private. The upper snippet of code then looks like:
Explicit rules
We can explicitly set the data-sharing attribute of a variable.
Shared
The shared(list)
clause declares that all the variables in
list
are shared. In the next example
n
and a
are shared variables.
OpenMP does not put any restriction to prevent data races between shared variables. This is a responsibility of a programmer.
Shared variables introduce an overhead, because one instance of a variable is shared between multiple threads. Therefore, it is often best to minimize the number of shared variables when a good performance is desired.
Private
The private(list)
clause declares that all the variables in
list
are private. In the next example
b
is a private variable. When a variable is declared private,
OpenMP replicates this variable and assigns its local copy to each thread.
The behavior of private variables is sometimes unintuitive. Let us assume that a private variable has a value before a parallel region. However, the value of the variable at the beginning of the parallel region is undefined. Additionally, the value of the variable is undefined also after the parallel region.
For example:
On several occasions, we can avoid listing private variables in the OpenMP constructs by declaring them inside a parallel region. For example, instead of
we can do
I highly encourage declaring private variables inside a parallel region whenever possible. This guideline simplifies the code and increases its readability.
Default
There are two versions of the default
clause. First, we focus
on default(shared)
option and then we consider
default(none)
clause.
These two versions are specific for C++ programmers of OpenMP. There are some
additional default
possibilities for Fortran programmers. For
more details look at the OpenMP specification on the page
189.
Default (shared)
The default(shared)
clause sets the data-sharing attributes
of all variables in the construct to shared. In the following example
a
, b
, c
and
n
are shared variables.
Another usage of default(shared)
clause is to specify the
data-sharing attributes of the majority of the variables and then additionally
define the private variables. Such usage is presented below:
Default (none)
The default(none)
clause forces a programmer to explicitly
specify the data-sharing attributes of all variables.
A distracted programmer might write the following piece of code
But then the compiler would complain
The reason for the unhappy compiler is that the programmer used
default(none)
clause and then she/he forgot to explicitly
specify the data-sharing attribute of a
. The correct version of the
program would be
Good practices
I warmly encourage that a programmer follows the next two guidelines.
The first guideline is to always write parallel regions with the
default(none)
clause. This forces the programmer to
explicitly think about the data-sharing attributes of all variables.
The second guideline is to declare private variables inside parallel regions whenever possible. This guideline improves the readability of the code and makes it clearer.
Summary
We studied the implicit and explicit rules for deducing the data-sharing attributes of variables. We also recommended a couple of good practices that a programmer should follow.
Links:
Jaka’s Corner OpenMP series: