Visible to Intel only — GUID: GUID-05555791-5237-4960-991F-AEAC0D30CACA
Visible to Intel only — GUID: GUID-05555791-5237-4960-991F-AEAC0D30CACA
DECLARE REDUCTION
OpenMP* Fortran Compiler Directive: Declares user-defined reductions which are identified by a reduction-identifier that can be used in a reduction clause of other directives.
Syntax
!$OMP DECLARE REDUCTION (reduction-identifier : type-list : combiner) [initializer-clause]
reduction-identifier |
Is a Fortran identifier, or a defined or extended operator. |
type-list |
Is a comma-separated list of one or more type identifiers. These may be intrinsic types or accessible derived types. You cannot specify polymorphic and parameterized derived types, and coarrays. type-list cannot contain a type which has previously been specified in a DECLARE REDUCTION directive with the same reduction-identifier if the reduction-identifier/type pair is accessible by use or host association. If more than one type is specified, it is as if there is a separate DECLARE REDUCTION directive for each type. |
combiner |
Is an assignment statement, or a subroutine name followed by an argument list. It indicates how partial results are combined into a single value. There are two special identifiers that are allowed in the combiner:
The above identifiers refer to variables that are the type of the reduction variables specified in type-list for the reduction-identifier. They denote values to be combined by executing the combiner. No other identifiers are permitted in the combiner. Any number of literal or named constants can appear in the combiner. If combiner is a subroutine name followed by an argument list, it is evaluated by calling the subroutine with the specified argument list. If combiner is an assignment statement, combiner is evaluated by executing the assignment statement. The number of times the combiner is executed, and the order of these executions, is unspecified. |
initializer-clause |
Is initializer (initializer-expression). At most one initializer-clause can be specified. Only the identifiers omp_priv and omp_orig are allowed in the initializer-clause. omp_orig refers to the storage of the original reduction variable that appears in the list in the REDUCTION clause that specifies reduction-identifier. If omp_orig is modified in the initializer-clause, the behavior is unspecified. No other identifiers are allowed in initializer-clause. Any number of literal or named constants are permitted. |
initializer-expression |
Is one of the following identifiers:
If initializer-expression is a subroutine name and an argument list, the initializer is evaluated by executing a call to the subroutine with the specified argument list. If initializer is an assignment statement, it is evaluated by executing the assignment. If initializer-expression is a subroutine name and an argument list, one of the arguments must be omp_priv, and it must be associated with an INTENT(OUT) dummy argument of the subroutine. The number of times initializer-expression is evaluated and the order of the evaluations is unspecified. |
The DECLARE REDUCTION directive is a specification directive. It can appear in a specification part of a subroutine, function, main program, module, or block construct.
User-defined (custom) reductions can be defined using the DECLARE REDUCTION directive. The reduction is identified by the reduction-identifier and the associated type from type-list. The reduction-identifier can be used in a REDUCTION clause in another OpenMP* directive anywhere it is accessible by use or host association.
A DECLARE REDUCTION directive cannot redefine a predefined reduction-identifier (see the table of implicitly defined reduction identifiers in the REDUCTION clause section).
If a type in type-list has deferred or assumed-length type parameters, the reduction-identifier can be used in a REDUCTION clause with a variable of the same type and kind type parameter as type, regardless of the length parameter with which the variable is declared. The length parameter of a character type must be a constant, colon, or asterisk. An accessible reduction-identifier defined with a deferred or assumed-length character type cannot appear in another DECLARE REDUCTION directive with a type-list item of type character with the same kind type parameter.
The accessibility of a reduction-identifier is determined by the same rules as for other Fortran entities; it can be declared PUBLIC or PRIVATE, be made accessible or blocked by a USE or IMPORT statement, and it can be renamed. If the reduction-identifier is the same as a generic name that is also the name of a derived type, the accessibility of the reduction-identifier is the same as that of the generic name.
If a subroutine or function used in initializer-expression or combiner is not an intrinsic procedure, it must have an accessible interface. Defined operators and defined assignments used in initializer or combiner must have accessible interfaces. All subroutines, functions, defined operators and defined assignments used in initializer or combiner must have accessible interfaces in the subprogram in which the corresponding REDUCTION clause appears. Procedures referenced in combiner and initializer cannot be alternate return subprograms.
The initial value of a user-defined reduction is not known before it is specified. The initializer-clause can be used to specify an initial value for the reduction variable. The initializer-clause will be executed to establish initial values for the private copies of reduction list items indicated in a REDUCTION clause that specifies the reduction-identifier.
If initializer is not specified, private reduction variables are initialized as follows:
If the reduction variable is type COMPLEX, REAL, or INTEGER, the default initializer is the value zero.
If the reduction variable specified in list of the REDUCTION clause is LOGICAL, the default initializer is the value .FALSE..
If the reduction variable is of a default initialized derived type, the default initializer value is used.
Otherwise, the initial value is unspecified.
If initializer is used in a target region, then a DECLARE TARGET construct (Linux* only) must be specified for any procedures that are executed during the execution of combiner or initializer.
If the execution of combiner or initializer results in the execution of an OpenMP* construct or an OpenMP* API call, the behavior is undefined. If the variable omp_orig is defined during execution of initializer, the behavior is unspecified.
Example
Consider that a DECLARE REDUCTION directive is used to declare a sum reduction for an integer component of a type my_type that is identified by the reduction-identifier '+'. It is then used in a REDUCTION clause of a parallel region to produce the sum of the thread numbers (numbered 1 thru 4) of the region:
module types
type my_type
integer :: component
end type
interface operator(+)
module procedure :: my_add
end interface
!$omp declare reduction (+ : my_type : omp_out = omp_out + omp_in) initializer (omp_priv = my_type (0))
contains
function my_add (a1, a2)
type(my_type),intent(in) :: a1, a2
type(my_type) :: my_add
my_add%component = a1%component + a2%component
return
end function my_add
end module types
program main
use types
use omp_lib
type(my_type) :: my_var
! Initialize the reduction variable before entering the OpenMP region
my_var%component = 0
!$omp parallel reduction (+ : my_var) num_threads(4)
my_var%component = omp_get_thread_num() + 1
!$omp end parallel
print *, "sum of thread numbers is ", my_var%component
end program
The output of the program follows:
sum of thread numbers is 10