Intel® Fortran Compiler Classic and Intel® Fortran Compiler Developer Guide and Reference

ID 767251
Date 3/22/2024
Public
Document Table of Contents

REDUCTION

Parallel Directive Clause: Performs a reduction operation on the specified variables.

Syntax

REDUCTION ([reduction-modifier, ]reduction-identifier : list)

reduction-modifier

Is INSCAN, TASK, or DEFAULT.

reduction-identifier

Is an identifier, user defined operator, or generic name which has appeared in an accessible DECLARE REDUCTION directive, or one of the predefined reduction operators or intrinsic names in the table of predefined reduction-identifiers below.

list

Is the name of one or more variables that are accessible to the scoping unit. Each list item must be definable. Each name must be separated by a comma. The type of each variable must be compatible with a type for which the reduction-identifier has an accessible definition.

Assumed-size arrays, procedure pointers, and dummy arguments that are pointers with the INTENT (IN) attribute are not allowed. Array sections are allowed.

For each list item, the number of copies is unspecified.

The same list item cannot appear in both a REDUCTION and an IN_REDUCTION clause in the same directive.

If a reduction-modifier is not present or if DEFAULT is specified for PARALLEL, LOOP, and worksharing constructs, one or more copies of each reduction list item is created for each implicit task in the region as if the list item had been specified in a PRIVATE clause.

If the REDUCTION clause appears in a SIMD statement, one or more private copies of each reduction list item is created for each SIMD lane. If the REDUCTION clause is in a TASKLOOP directive, private copies of reduction list items are created as if a PRIVATE clause had been specified containing the list item. For a REDUCTION clause in a TEAMS construct, one or more private copies of each reduction list item are created for the initial task of each team in the league.

The TASK reduction-modifier can only appear in a REDUCTION clause of a PARALLEL or worksharing construct or in a combined construct for which one of these constructs is a constituent member and the SIMD and LOOP construct are not constituent members. If the TASK reduction-modifier is specified for a PARALLEL or worksharing construct, it is as if each reduction list item appeared in a PRIVATE clause in the directive, and any number of additional private copies can be created to support task reductions. If the TASK reduction-modifier appears in a REDUCTION clause, a NOWAIT clause cannot appear for the same construct.

List items in a REDUCTION clause of the inner most enclosing worksharing or PARALLEL construct must not be accessed in an explicit task generated by a construct unless that construct contains an IN_REDUCTION clause that contains the same list items.

The INSCAN reduction-modifier is allowed only in a worksharing construct, a SIMD construct, or a composite construct for which these constructs are a constituent construct, and the DISTRIBUTE is not a constituent construct. It indicates that in each iteration of the loop, a scan computation is performed over the updates to each list item. Each list item is made PRIVATE in the construct. Upon completion of the region, the value of the private copy of a list item from the last logical iteration of the loops of the construct is assigned to the original list item.

Each list item of a REDUCTION clause with the INSCAN reduction-modifier must appear as a list item in an INCLUSIVE or EXCLUSIVE clause in a SCAN directive contained in the loop (nest) enclosed in the construct. If INSCAN appears in one REDUCTION clause of a construct, all REDUCTION clauses of that construct must contain an INSCAN reduction-modifier. If an INSCAN reduction-modifier is applied to a construct that is combined with a TARGET construct, it is as if each list item also appears in a MAP clause with a map-type of TOFROM.

Variables that appear in a REDUCTION clause must be SHARED in the enclosing context. A private copy of each variable in list is created for each thread as if the PRIVATE clause had been used. The private copy is initialized according to the initializer-clause of the reduction-identifier. A dummy argument that is a pointer with the INTENT (IN) attribute must not appear in a REDUCTION clause.

At the end of the REDUCTION, the shared variable is updated to reflect the result of combining the original value of the shared reduction variable with the final value of each of the private copies using the combiner specified for the reduction-identifier. Reduction operations should all be associative (except for subtraction), and the compiler can freely reassociate the computation of the final value; the partial results of a subtraction reduction are added to form the final value.

The value of the shared variable becomes undefined when the first thread reaches the clause containing the reduction, and it remains undefined until the reduction computation is complete. Normally, the computation is complete at the end of the construct containing the REDUCTION clause.

However, if the REDUCTION clause is used in a construct to which NOWAIT is also applied, the shared variable remains undefined until a barrier synchronization has been performed. This ensures that all the threads complete the REDUCTION clause.

Any list item copies associated with the reduction must be initialized before they are accessed by the tasks participating in the reduction. After the end of the region, the original list item contains the result of the reduction.

An original list item with the POINTER attribute, or any pointer component of an original list item that is referenced, must be associated at entry to the construct that contains the REDUCTION clause. Also, the list item, or the pointer component of the list item, must not be deallocated, allocated, or pointer assigned within the region.

An original list item with the ALLOCATABLE attribute, or any allocatable component of an original list item that is referenced, must be in the allocated state at entry to the construct that contains the REDUCTION clause. Also, the list item, or the allocatable component of the list item, must be neither deallocated nor allocated within the region.

Any number of REDUCTION clauses can be specified on the directive, but a list item can appear only once in REDUCTION clauses for that directive.

If a list item is an array section, the following applies:

  • The array section must specify contiguous storage and it cannot be a zero-length array section.

  • Accesses to the elements of the array outside the specified array section result in unspecified behavior.

  • The reduction clause will be applied to each separate element of the array section.

  • Access to the elements of the array outside the specified array section result in unspecified behavior.

The following table lists predefined reduction-identifiers. These reduction-identifiers are implicitly defined and cannot be redefined in a DECLARE REDUCTION directive for the types shown here. The actual initialization value will be consistent with the data type of the reduction variable.

Predefined reduction-identifiers

reduction-identifier

Type

Combiner

Initializer

+

INTEGER, REAL, COMPLEX

omp_out = omp_out + omp_in

omp_priv = 0

*

INTEGER, REAL, COMPLEX

omp_out = omp_out * omp_in

omp_priv = 1

-

INTEGER, REAL, COMPLEX

omp_out = omp_out + omp_in

omp_priv = 0

.AND.

LOGICAL

omp_out = omp_out .AND. omp_in

omp_priv = .TRUE.

.OR.

LOGICAL

omp_out = omp_out .OR. omp_in

omp_priv = .FALSE.

.EQV.

LOGICAL

omp_out = omp_out .EQV. omp_in

omp_priv = .TRUE.

.NEQV.

LOGICAL

omp_out = omp_out .NEQV. omp_in

omp_priv = .FALSE.

MAX

INTEGER, REAL

omp_out = max (omp_out, omp_in)

omp_priv =Smallest representable number

MIN

INTEGER, REAL

omp_out = min (omp_out, omp_in)

omp_priv = Largest representable number

IAND

INTEGER

omp_out = iand (omp_out, omp_in)

omp_priv = All bits set

IOR

INTEGER

omp_out = ior (omp_out, omp_in)

omp_priv = 0

IEOR

INTEGER

omp_out = ieor (omp_out, omp_in)

omp_priv = 0

If a directive allows REDUCTION clauses, the number you can specify is not limited. However, each variable name can appear only once in only one of the clauses.

NOTE:

If a variable appears in a REDUCTION clause on a combined construct for which the first construct is TARGET, it is treated as if it had appeared in a MAP clause with a map-type of TOFROM.

Example

In the following program fragment, time will be the sum of the time spent in the do loop across all threads:

  use omp_lib
  integer i
  double precision t1, time
  call omp_set_num_threads(4)
  ...
!$omp do reduction(+:time) 
  do i = 1, omp_get_num_threads()
    t1 = omp_get_wtime()
    ...
    time = omp_get_wtime() – t1
  end do
  !here time is equal to the total time across all threads
  ...