Developer Guide and Reference

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

DO CONCURRENT

Statement: Specifies that there are no data dependencies between the iterations of a DO loop.

The DO CONCURRENT statement takes the following form:

[name:] DO [label [,]] CONCURRENT concurrent-header [locality-spec]

   block

[END DO [name]]

name

(Optional) Is the name of the DO CONCURRENT construct.

concurrent-header

Is ( [ type :: ] concurrent-spec [, mask-expr] )

If type appears, the index-name has the specified type and type parameters. Otherwise, it has the type and type parameters that it would have if it were the name of a variable in the innermost executable construct or scoping unit.

If type is omitted, the index-name must not be the same as a local identifier, an accessible global identifier, or an identifier of an outer construct entity, except for a common block name or a scalar variable name.

type

(Optional) Is an integer data type.

concurrent-spec

Is an assignment using a triplet specification in the form index-name = concurrent-limit : concurrent-limit [ : concurrent-step]

index-name

Is a named scalar variable of type integer. It becomes defined when the index-name value set is evaluated. It has the scope of the construct.

The index-name of a contained FORALL or DO CONCURRENT construct must not be the same as an index-name of any of its containing FORALL or DO CONCURRENT constructs.

concurrent-limit

Is a scalar integer expression.

concurrent-step

(Optional) Is a scalar integer expression.

mask-expr

(Optional) Is a masked expression that is scalar and of type logical.

Any procedure referenced in mask-expr must be pure, including one referenced by a defined operator.

index-name can appear in mask-expr. The set of index values to be executed is the set of all index-name values for which mask-expr is true.

label

(Optional) Is a label specifying an executable statement in the same program unit.

locality-spec

(Optional) Can be any of the following:

  • DEFAULT (NONE)

    You can specify DEFAULT (NONE) only once in a DO CONCURRENT statement. If specified, any variable or construct entity that is accessible in the scope containing the DO CONCURRENT statement that appears in the block of the DO CONCURRENT construct must have its locality explicitly specified.

  • LOCAL (variable-name-list)

  • LOCAL_INIT (variable-name-list)

  • REDUCE (reduction-oper : variable-name-list)

    reduction-oper is one of the intrinsic binary-reduction-operators +, *, .AND., .OR., .EQV., or .NEQV., or one of the intrinsic function-reduction-operator names IAND, IEOR, IOR, MAX or MIN.

    A variable in variable-name-list cannot be coindexed, be an assumed-size array, or have the ASYNCHRONUS, INTENT(IN), OPTIONAL, or VOLATILE attribute. It must be of an intrinsic type that is compatible with the intrinsic reduction-oper.

  • SHARED (variable-name-list)

    References in a DO CONCURRENT construct to a SHARED variable are references to the variable in the innermost construct or scope containing the DO CONCURRENT construct.

    If the variable is defined or becomes undefined in one iteration, it cannot be referenced, defined, or become undefined in another iteration.

    If the variable becomes pointer assigned, allocated, deallocated, or nullified in an iteration, its dynamic type, allocation or allocations status, shape, bounds, or a deferred-type parameter cannot be inquired about in another iteration.

    A SHARED noncontiguous array cannot be used as an actual argument associated with a contiguous INTENT(INOUT) dummy argument within the construct.

You can specify LOCAL, LOCAL_INIT, REDUCE, SHARED, and DEFAULT (NONE) in the same DO CONCURRENT statement.

You can specify more than one of the following in the same DO CONCURRENT statement: LOCAL, LOCAL_INIT, REDUCE, and SHARED.

block

Is a sequence of zero or more statements or constructs that make up the DO range.

A variable that appears in a mask-expr, concurrent-step, or concurrent-limit of a concurrent-header, cannot appear in a LOCAL locality-spec in the same DO CONCURRENT statement.

If a construct name is specified in a DO CONCURRENT statement, the same name must appear in a terminal END DO statement. If no construct name is specified in the DO CONCURRENT statement, no name can appear in the terminal END DO statement, if one is specified.

If END DO is specified, it terminates the construct. If END DO is not specified, when all of the iterations have completed execution, the loop terminates, and the DO construct becomes inactive. You can branch to the END DO statement only from within the construct.

When the DO CONCURRENT construct terminates, a variable that is defined or becomes undefined during more than one iteration of the construct becomes undefined.

The DO CONCURRENT range is executed for every active combination of the index-name values.

Each execution of the range is an iteration. The executions can occur in any order.

Execution of a CYCLE statement that belongs to a DO CONCURRENT construct completes execution of that iteration of the construct.

A branch within a DO CONCURRENT construct must not have a branch target that is outside the construct.

The following cannot appear in a DO CONCURRENT construct:

  • A RETURN statement

  • An image control statement

  • A branch to a target outside the construct block

  • A statement that may result in the deallocation of a polymorphic variable

  • An input/output statement with an ADVANCE= specifier

  • A reference to a nonpure procedure

  • A reference to module IEEE_EXCEPTIONS procedure IEEE_GET_FLAG, IEEE_SET_HALTING_MODE, IEEE GET_STATUS, IEEE_SET_MODES, IEEE_SET_STATUS, or IEEE_GET_HALTING_MODE

  • A reference to module IEEE_ARITHMETIC procedure IEEE_SET_ROUNDING_MODE or IEE_SET_UNDERFLOW_MODE

An EXIT statement must not appear within a DO CONCURRENT construct if it belongs to that construct or an outer construct.

A variable with LOCAL or LOCAL_INIT locality is a construct entity with the same type, type parameters, and rank as variable with the same name in the innermost construct or scope containing the DO CONCURRENT construct. The variable outside the construct is inaccessible by that name inside the DO CONCURRENT construct.

The following are rules for variable-name in a locality-spec:

  • A variable-name must be the name of a variable that is accessible in the innermost construct containing the DO CONCURRENT statement. variable-name can appear at most once in any locality-spec of a DO CONCURRENT statement. It cannot be the same as index-name of the same DO CONCURRENT statement.

  • A variable-name in a LOCAL or LOCAL_INIT locality-spec cannot have the OPTIONAL, ALLOCATABLE, or INTENT(IN) attribute, it cannot be a non-pointer polymorphic dummy argument, a coarray or an assumed-size array, or be of a type that is finalizable.

  • variable-name is not permitted in a LOCAL, LOCAL_INIT, or REDUCE locality-spec if it is not permitted in a variable-definition context.

At the beginning of each iteration, a variable with LOCAL locality that is a pointer has pointer association status of undefined; otherwise, it is undefined except for any subobjects that are default initialized. A variable with LOCAL_INIT locality has the definition status and pointer association status of the variable outside the construct. The variable outside the construct cannot be an undefined nonallocatable nonpointer variable, or an undefined pointer.

A variable with the REDUCE locality is a construct entity with the same type, type parameters, rank, and bounds as the variable with the same name in the innermost construct or scope containing the DO CONCURRENT construct (outside variable). Within the construct, the outside variable is inaccessible by that name. The following are additional rules:

  • If the outside variable has the ALLOCATABLE attribute, it must be allocated; if it has the POINTER attribute, it must be associated.

  • If the outside variable has the CONTIGUOUS attribute, the construct entity has the CONTIGUOUS attribute.

  • The construct entity does not have the ALLOCATABLE, BIND, INTENT, POINTER, PROTECTED, SAVE, TARGET, or VALUE attribute, even if the outside variable does. The construct entity is initialized with the value of the reduction-oper as specified in the following table prior to beginning execution of the iterations:

    The reduction-oper

    Initial Value of Construct Entity

    +

    0

    *

    1

    .AND.

    .TRUE.

    .EQV.

    .TRUE.

    .NEQV.

    .FALSE.

    .OR.

    .FALSE.

    IAND

    All bits set

    IEOR

    0

    IOR

    0

    MAX

    Largest representable value for type and kind

    MIN

    Smallest representable value for type and kind

In the block of a DO CONCURRENT construct, variables with REDUCE locality can only appear in the designator of a variable, as the object name, or as the leftmost part name of an array element or array section in an intrinsic assignment statement that takes one of the following forms:

variable = variable binary-reduction-operator expr
variable = expr binary-reduction-operator variable
variable = function-reduction-operator ([expr ,]... variable [, expr ] ...)

Each occurrence of variable in the statement must have the same form.

When the DO CONCURRENT construct completes, the outside variable of a variable with REDUCE locality is updated by combining the outside value with the values of the associated construct entities upon completion of the construct using reduction-operator. This combination can occur in any order.

A pointer that becomes associated with a LOCAL or LOCAL_INIT TARGET variable becomes undefined at the end of the iteration. If a LOCAL or LOCAL_INIT variable appears in an input/output statement, the input/output operation must complete before the iteration completes.

A construct or statement entity with the SAVE attribute and with unspecified locality in a DO CONCURRENT construct has SHARED locality. If it does not have the SAVE attribute, it is a different entity in each iteration of the construct.

The construct entity does not have the BIND, SAVE, VALUE, PROTECTED, or INTENT attribute, even if the variable with the same name outside the construct has the attribute. The construct entity does have the VOLATILE, CONTIGUOUS, POINTER, TARGET, or ASYNCHRONOUS attribute if the variable outside the construct with the same name has the attribute. If it is a non-pointer, it has the same bounds as the variable outside the construct.

The following are rules for variables with unspecified locality in DO CONCURRENT constructs:

  • A variable that is referenced in an iteration must be previously defined during that iteration, or it must not be defined or become undefined during any other iteration.

    A variable that is defined or becomes undefined by more than one iteration becomes undefined when the loop terminates.

  • An allocatable object that is allocated in more than one iteration must be subsequently deallocated during the same iteration in which it was allocated.

    An object that is allocated or deallocated in only one iteration must not be referenced, allocated, deallocated, defined, or become undefined in a different iteration.

  • A pointer that is referenced in an iteration must have been pointer associated previously during that iteration, or it must not have its pointer association changed during any iteration.

    A pointer that has its pointer association changed in more than one iteration has an association status of undefined when the construct terminates.

  • An input/output statement must not write data to a file record or position in one iteration and read from the same record or position in a different iteration.

  • Records written by output statements in the range of the loop to a sequential-access file appear in the file in an indeterminate order.

The restrictions on referencing variables defined in an iteration of a DO CONCURRENT construct also apply to any procedure invoked within the loop. These restrictions ensure no interdependencies occur that might affect code optimizations.

NOTE:

If compiler option [q or Q]openmp or option [Q]parallel is specified, the compiler will attempt to parallelize the construct.

NOTE:

If compiler option -fopenmp-target-do-concurrent (Linux) or /Qopenmp-target-do-concurrent (Windows) is specified, the compiler will attempt to convert the construct into an OpenMP TARGET offload region. An I/O statement in the construct will inhibit conversion to a TARGET region; it can still be parallelized.

See the DO statement for the semantics of labeled and block forms of DO loops.

The labeled form of a DO CONCURRENT loop is an obsolescent feature in the Fortran Standard.

Examples

The following example shows a DO CONCURRENT construct with a mask-expr and locality specified for variables:

INTEGER,DIMENSION(N) :: J, K
INTEGER              :: I, M
M = 10
I = 15
DO CONCURRENT (I = 1:N, J(I)> 0)LOCAL (M) SHARED (J, K)
   M =  MOD (K(I), J(I))
   K(I) = K(I) – M
END DO
PRINT *, I, M             ! Prints 15 10

The following example shows a DO CONCURRENT construct that has a variable with REDUCE locality. The variable has a value of 100 prior to the DO CONCURRENT construct. The values of the array are added to the variable in a sum reduction of the array:

INTEGER,DIMENSION(10) :: ARRAY
INTEGER               :: I, SUM_PLUS_100 = 100

ARRAY = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
DO CONCURRENT (I = 1:10) REDUCE (+ : SUM_PLUS_100)
   SUM_PLUS_100 = SUM_PLUS_100 + ARRAY(I)
END DO
PRINT *, SUM_PLUS_100   ! Prints 155