インテル® Fortran コンパイラー 19.0 デベロッパー・ガイドおよびリファレンス

REDUCTION

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

REDUCTION (reduction-identifier : list)

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.

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 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
  ...

See Also