| CF90TM Commands and Directives Reference Manual | ||
|---|---|---|
| Prev Section | Chapter 4. OpenMP Fortran API Directives (UNICOS Systems Only) | Next Section |
The following sections describe the synchronization constructs:
Section 4.6.1, describes the MASTER and END MASTER directives.
Section 4.6.2, describes the CRITICAL and END CRITICAL directives.
Section 4.6.3, describes the BARRIER directive.
Section 4.6.4, describes the ATOMIC directive.
Section 4.6.5, describes the FLUSH directive.
Section 4.6.6, describes the ORDERED and END ORDERED directives.
The code enclosed within MASTER and END MASTER directives is executed by the master thread.
These directives have the following format:
|
| block | Denotes a structured block of Fortran statements. You cannot branch into or out of the block. |
The other threads in the team skip the enclosed section of code and continue execution. There is no implied barrier either on entry to or exit from the master section.
The CRITICAL and END CRITICAL directives restrict access to the enclosed code to one thread at a time.
These directives have the following format:
|
A thread waits at the beginning of a critical section until no other thread in the team is executing a critical section with the same name. All unnamed CRITICAL directives map to the same name. Critical section names are global entities of the program. If a name conflicts with any other entity, the behavior of the program is undefined.
Example. The following code fragment includes several CRITICAL directives. The example illustrates a queuing model in which a task is dequeued and worked on. To guard against multiple threads dequeuing the same task, the dequeuing operation must be in a critical section. Because there are two independent queues in this example, each queue is protected by CRITICAL directives with different names, XAXIS and YAXIS, respectively.
!$OMP PARALLEL DEFAULT(PRIVATE) SHARED(X,Y)
!$OMP CRITICAL(XAXIS)
CALL DEQUEUE(IX_NEXT, X)
!$OMP END CRITICAL(XAXIS)
CALL WORK(IX_NEXT, X)
!$OMP CRITICAL(YAXIS)
CALL DEQUEUE(IY_NEXT,Y)
!$OMP END CRITICAL(YAXIS)
CALL WORK(IY_NEXT, Y)
!$OMP END PARALLEL |
The BARRIER directive synchronizes all the threads in a team. When it encounters a barrier, a thread waits until all other threads in that team have reached the same point.
This directive has the following format:
!$OMP BARRIER |
The ATOMIC directive ensures that a specific memory location is updated atomically, rather than exposing it to the possibility of multiple, simultaneous writing threads.
This directive has the following format:
!$OMP ATOMIC |
This directive applies only to the immediately following statement, which must have one of the following forms:
|
In the preceding statements:
x is a scalar variable of intrinsic type. All references to storage location x must have the same type and type parameters.
expr is a scalar expression that does not reference x.
intrinsic is one of MAX, MIN, IAND, IOR, or IEOR.
operator is one of +, *, -, /, .AND., .OR., .EQV., or .NEQV. .
Only the load and store of x are atomic; the evaluation of expr is not atomic. To avoid race conditions, all updates of the location in parallel must be protected with the ATOMIC directive, except those that are known to be free of race conditions.
Example 1. The following code fragment uses the ATOMIC directive:
!$OMP ATOMIC
X(INDEX(I)) = Y(INDEX(I)) + B |
Example 2. The following code fragment avoids race conditions by protecting all simultaneous updates of the location, by multiple threads, with the ATOMIC directive:
!$OMP PARALLEL DO DEFAULT(PRIVATE) SHARED(X,Y,INDEX,N)
DO I=1,N
CALL WORK(XLOCAL, YLOCAL)
!$OMP ATOMIC
X(INDEX(I)) = X(INDEX(I)) + XLOCAL
Y(I) = Y(I) + YLOCAL
ENDDO |
Note that the ATOMIC directive applies only to the Fortran 90 statement that immediately follows it. As a result, Y is not updated atomically in the preceding code.
The FLUSH directive identifies synchronization points at which thread-visible variables are written back to memory. This directive must appear at the precise point in the code at which the synchronization is required.
Thread-visible variables include the following data items:
Globally visible variables (common blocks and modules)
Local variables that do not have the SAVE attribute but have had their address taken and saved or have had their address passed to another subprogram
Local variables that do not have the SAVE attribute that are declared shared in a parallel region within the subprogram
Dummy arguments
All pointer dereferences
This directive has the following format:
!$OMP FLUSH [(var[, var] ...)] |
| var | Variables to be flushed. |
An implicit FLUSH directive is assumed for the following directives:
BARRIER
CRITICAL and END CRITICAL
END DO
END PARALLEL
END SECTIONS
END SINGLE
ORDERED and END ORDERED
The directive is not implied if a NOWAIT clause is present.
Example. The following example uses the FLUSH directive for point-to-point synchronization between pairs of threads:
!$OMP PARALLEL DEFAULT(PRIVATE) SHARED(ISYNC)
IAM = OMP_GET_THREAD_NUM()
ISYNC(IAM) = 0
!$OMP BARRIER
CALL WORK()
!
!I AM DONE WITH MY WORK, SYNCHRONIZE WITH MY NEIGHBOR
!
ISYNC(IAM) = 1
!$OMP FLUSH(ISYNC)
!
!WAIT TILL NEIGHBOR IS DONE
!
DO WHILE (ISYNC(NEIGH) .EQ. 0)
!$OMP FLUSH(ISYNC)
END DO
!$OMP END PARALLEL |
The code enclosed within ORDERED and END ORDERED directives is executed in the order in which it would be executed in a sequential execution of an enclosing parallel loop.
These directives have the following format:
|
| block | Denotes a structured block of Fortran statements. You cannot branch into or out of the block. |
An ORDERED directive can appear only in the dynamic extent of a DO or PARALLEL DO directive. This DO directive must have the ORDERED clause specified. For more information on the DO directive, see Section 4.4.1. For information on directive binding, see Section 4.8.
Only one thread is allowed in an ordered section at a time. Threads are allowed to enter in the order of the loop iterations. No thread can enter an ordered section until it is guaranteed that all previous iterations have completed or will never execute an ordered section. This sequentializes and orders code within ordered sections while allowing code outside the section to run in parallel. ORDERED sections that bind to different DO directives are independent of each other.
The following restrictions apply to the ORDERED directive:
An ORDERED directive cannot bind to a DO directive that does not have the ORDERED clause specified.
An iteration of a loop with a DO directive must not execute the same ORDERED directive more than once, and it must not execute more than one ORDERED directive.
Example. Ordered sections are useful for sequentially ordering the output from work that is done in parallel. Assuming that a reentrant I/O library exists, the following program prints out the indexes in sequential order:
!$OMP DO ORDERED SCHEDULE(DYNAMIC)
DO I=LB,UB,ST
CALL WORK(I)
END DO
SUBROUTINE WORK(K)
!$OMP ORDERED
WRITE(*,*) K
!$OMP END ORDERED
END |
| Prev Section | Table of Contents | Title Page | Next Section |
| Combined Parallel Work-sharing Constructs | Up one level | Data Environment Constructs |