accessibility of variable names in serial programming languages (such as local, file-level, and global in C,
or local and common in Fortran). For clarity, we will consistently use the term "lexical scope" when we
intend the latter, serial programming language sense, and plain "scope" when referring to whether a
variable is shared between OpenMP threads. In addition, "scope" is both a noun and a verb: every
variable used within an OpenMP construct has a scope, and we can explicitly scope a variable as shared
or private on an OpenMP construct by adding a clause to the directive that begins the construct.
Although shared variables make it convenient for threads to communicate, the choice of whether a
variable is to be shared or private is dictated by the requirements of the parallel algorithm and must be
made carefully. Both the unintended sharing of variables between threads, or, conversely, the
privatization of variables whose values need to be shared, are among the most common sources of errors
in shared memory parallel programs. Because it is so important to give variables correct scopes,
OpenMP provides a rich set of features for explicitly scoping variables, along with a well-defined set of
rules for implicitly determining default scopes. These are all of the scoping clauses that can appear on a
parallel construct:
shared and private explicitly scope specific variables.
firstprivate and lastprivate perform initialization and finalization of privatized variables.
default changes the default rules used when variables are not explicitly scoped.
reduction explicitly identifies reduction variables.
We first describe some general properties of data scope clauses, and then discuss the individual scope
clauses in detail in subsequent sections.
3.4.1 General Properties of Data Scope Clauses
A data scope clause consists of the keyword identifying the clause (such as shared or private), followed
by a comma-separated list of variables within parentheses. The data scoping clause applies to all the
variables in the list and identifies the scope of these variables as either shared between threads or private
to each thread.
Any variable may be marked with a data scope clause—automatic variables, global variables (in C/C++),
common block variables or module variables (in Fortran), an entire common block (in Fortran), as well as
formal parameters to a subroutine. However, a data scope clause does have several restrictions.
The first requirement is that the directive with the scope clause must be within the lexical extent of the
declaration of each of the variables named within a scope clause; that is, there must be a declaration of
the variable that encloses the directive.
Second, a variable in a data scoping clause cannot refer to a portion of an object, but must refer to the
entire object. Therefore, it is not permitted to scope an individual array element or field of a structure—the
variable must be either shared or private in its entirety. A data scope clause may be applied to a variable
of type struct or class in C or C++, in which case the scope clause in turn applies to the entire structure
including all of its subfields. Similarly, in Fortran, a data scope clause may be applied to an entire
common block by listing the common block name between slashes ("/"), thereby giving an explicit scope
to each variable within that common block.
Third, a directive may contain multiple shared or private scope clauses; however, an individual variable
can appear on at most a single clause—that is, a variable may uniquely be identified as shared or private,
but not both.
Finally, the data scoping clauses apply only to accesses to the named variables that occur in the code
contained directly within the parallel do/ end parallel do directive pair. This portion of code is referred to
as the lexical extent of the parallel do directive and is a subset of the larger dynamic extent of the
directive that also includes the code contained within subroutines invoked from within the parallel loop.
Data references to variables that occur within the lexical extent of the parallel loop are affected by the
data scoping clauses. However, references from subroutines invoked from within the parallel loop are not
affected by the scoping clauses in the dynamically enclosing parallel directive. The rationale for this is
simple: References within the lexical extent are easily associated with the data scoping clause in the
directly enclosing directive. However, this association is far less obvious for references that are outside
the lexical scope, perhaps buried within a deeply nested chain of subroutine calls. Identifying the relevant
data scoping clause would be extremely cumbersome and error prone in these situations. Example 3.2
shows a valid use of scoping clauses in Fortran.
Example 3.2: Sample scoping clauses in Fortran.