Visible to Intel only — GUID: GUID-14AC3DF4-ADB9-4039-A879-7D435E15A84D
Visible to Intel only — GUID: GUID-14AC3DF4-ADB9-4039-A879-7D435E15A84D
ORDERED
OpenMP* Fortran Compiler Directive: Specifies a block of code that the threads in a team must execute in the natural order of the loop iterations, or, as a stand-alone directive, it specifies cross-iteration dependences in a doacross loop nest.
Syntax
It takes one of the following forms:
Form 1:
!$OMP ORDERED [clause [[,] clause ]]
loosely-structured-block
!$OMP END ORDERED
-or-
!$OMP ORDERED [clause [[,] clause ]]
strictly-structured-block
[!$OMP END ORDERED]
Form 2:
!$OMP ORDERED clause [[[,] clause ]...]
Form 1 clause |
Is an optional clause. It can be one of the following:
At most one THREADS clause can appear in an ORDERED construct. At most one SIMD clause can appear in an ORDERED construct. |
Form 2 clause |
Is one of the following:
At most one DOACROSS clause can appear in an ORDERED construct if SOURCE is specified. Either DOACROSS (SINK : vec) clauses or DOACROSS (SOURCE :) clauses can appear in an ORDERED construct, but not both. vec is an iteration vector that specifies the iteration of the loop or loop nest that satisfies the dependency. If vec has n elements, the innermost loop-associated construct that encloses the ORDERED directive must specify an ORDERED clause whose parameter value is also n. The predefined dependence vector OMP_CUR_ITERATION specifies the current iteration. If DOACROSS (SINK : OMP_CUR_ITERATION – 1) appears in a triply nested loop with loop indices i, j, and k, the effect is the same as if DOACROSS (SINK : i-1, j-1, k-1) was specified. |
loosely-structured-block |
Is a structured block (section) of statements or constructs. You cannot branch into or out of the block. |
strictly-structured-block |
Is a Fortran BLOCK construct. You cannot branch into or out of the BLOCK construct. |
The binding thread set for an ORDERED construct is the current team. An ordered region binds to the innermost enclosing loop region or the innermost enclosing SIMD region if the SIMD clause is present.
A doacross loop nest is a loop nest that has cross-iteration dependences. An iteration is dependent on one or more lexicographically earlier iterations. The ORDERED clause parameter on a loop directive identifies the loops associated with the doacross loop nest.
An ORDERED directive with no clause or with the THREADS clause specified can appear only in the dynamic extent of a DO or PARALLEL DO directive. The DO directive to which the ordered section binds must have the ORDERED clause specified.
An iteration of a loop using a DO directive must not execute the same ORDERED directive more than once, and it must not execute more than one ORDERED directive.
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 can be 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.
If the SIMD clause is specified, the ordered regions encountered by any thread will use only a single SIMD lane to execute the ordered regions in the order of the loop iterations.
You can only specify the SIMD clause (!$OMP ORDERED SIMD) within an !$OMP SIMD loop or an !$OMP DECLARE SIMD procedure.
When a thread executing any subsequent iteration encounters an ORDERED construct with one or more DOACROSS clauses specifying SINK, it waits until its dependences on all valid iterations specified by the DOACCROSS clauses are satisfied before it completes execution of the ORDERED region. A specific dependence is satisfied when a thread executing the corresponding iteration encounters an ORDERED construct with a DOACCROSS clause specifying SOURCE.
For MONOTONIC (list: linear-step), the following rules apply:
The value of the new list item on each iteration of the associated SIMD loop corresponds to the value of the original list item before entering the associated loop, plus the number of the iterations for which the conditional update happens prior to the current iteration, times linear-step.
The value corresponding to the sequentially last iteration of the associated loop is assigned to the original list item.
A list item must not be used in statements that lexically precede the ORDERED SIMD to which it is bound, that is, in the region from the OMP SIMD to the OMP ORDERED SIMD. A list item must not be modified outside the ORDERED SIMD to which it is bound, that is, in the region from the OMP END ORDERED to the OMP END SIMD.
This construct is not supported within a TARGET or a DECLARE TARGET region if the target hardware is spir64.
Examples
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
Ordered SIMD sections are useful for resolving cross-iteration data dependencies in otherwise data-parallel computations. For example, it may handle histogram updates such the following:
!$OMP SIMD
DO I=0,N
AMOUNT = COMPUTE_AMOUNT(I)
CLUSTER = COMPUTE_CLUSTER(I) ! Multiple I's may belong to the
! same cluster within SIMD chunk
!$OMP ORDERED SIMD
TOTALS(CLUSTER) = TOTALS(CLUSTER) + AMOUNT ! Requires ordering to
! process multiple updates
! to the same cluster
!$OMP END ORDERED
END DO
!$OMP END SIMD
The MONOTONIC keyword in the OMP ORDERED SIMD directive specifies that the body of a loop must be executed in the natural order of the loop iterations. In the following example, the block of code in the OMP ORDERED SIMD is executed in the ascending, monotonic order of the loop index I:
COUNT = 0 !$OMP SIMD DO I = 1, N IF (COND(I)) THEN !$OMP ORDERED SIMD MONOTONIC (COUNT:1) A(COUNT) = A(COUNT) + B(I) COUNT = COUNT + 1 B(I) = C(COUNT) !$OMP END ORDERED END IF END DO !$OMP END SIMD
In the following example, the OVERLAP keyword specifies that the block of code after the OMP ORDERED SIMD directive may contain overlap between the loop iterations:
!$OMP SIMD DO I = 1, N INX = INDEX(I) !$OMP ORDERED SIMD OVERLAP (INX) A(INX) = A(INX) + B(I) !$OMP END ORDERED END DO !$OMP END SIMD