Developer Guide and Reference

ID 767251
Date 10/31/2024
Public
Document Table of Contents

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:

  • SIMD [keyword [, keyword]...]

    Binds the ordered region to the innermost SIMD or worksharing loop region. With ifx, you can specify one or more keywords to apply an ordered region inside a SIMD loop. Possible values are:

    • MONOTONIC (list [ : linear-step ] )

      The list is a comma-separated list of one or more integer scalar variables. The linear-step is a positive, integer, scalar constant expression. The linear-step expression must be invariant (it must not be changed) during the execution of the associated construct. If linear-step is omitted, a default value of 1 is used.

      Multiple MONOTONIC keywords may appear; they are merged into a single MONOTONIC list. You cannot specify multiple MONOTONIC keywords with different linear-steps for the same variable.

      Each list item may have the POINTER attribute but not the ALLOCATABLE attribute. Each list item must comply with PRIVATE clause semantics.

    • OVERLAP (expr)

      The expr is an integer expression. It specifies a block of code that has to be executed in scalar mode for overlapping loop index values and in parallel for different loop index values within the SIMD loop.

      The OVERLAP keyword can appear no more than once in an ORDERED directive.

  • THREADS

    Applies an ordered region inside a PARALLEL DO loop. If no clause is specified, the directive behaves as if THREADS was specified.

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:

  • DOACROSS (SOURCE : [ OMP_CUR_ITERATION ])

  • DOACROSS (SINK : vec)

  • DOACROSS (SINK : OMP_CUR_ITERATION – 1)

  • DEPEND (SOURCE) - deprecated

  • DEPEND (SINK : vec) - deprecated

    The above DEPEND clauses have been deprecated and replaced by DOACROSS clauses. The semantics of DEPEND and DOACROSS are similar.

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.

NOTE:

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