HOME
| OPENMP API Specification: Version 5.1 November 2020

2.21.5  Reduction Clauses and Directives

The reduction clauses are data-sharing attribute clauses that can be used to perform some forms of recurrence calculations in parallel. Reduction clauses include reduction scoping clauses and reduction participating clauses. Reduction scoping clauses define the region in which a reduction is computed. Reduction participating clauses define the participants in the reduction.

2.21.5.1 Properties Common to All Reduction Clauses

Syntax The syntax of a reduction-identifier is defined as follows:

SVG-Viewer needed.

A reduction-identifier is either an identifier or one of the following operators: +, -, *, &, |, ^, && and ||.

SVG-Viewer needed.

SVG-Viewer needed.

A reduction-identifier is either an id-expression or one of the following operators: +, -, *, &, |, ^, && and ||.

SVG-Viewer needed.

SVG-Viewer needed.

A reduction-identifier is either a base language identifier, or a user-defined operator, or one of the following operators: +, -, *, .and., .or., .eqv., .neqv., or one of the following intrinsic procedure names: max, min, iand, ior, ieor.

SVG-Viewer needed.

SVG-Viewer needed.

Table 2.11 lists each reduction-identifier that is implicitly declared at every scope for arithmetic types and its semantic initializer value. The actual initializer value is that value as expressed in the data type of the reduction list item.

Table 2.11: Implicitly Declared C/C++ reduction-identifiers



Identifier Initializer Combiner



+ omp_priv = 0 omp_out += omp_in
- omp_priv = 0 omp_out += omp_in
* omp_priv = 1 omp_out *= omp_in
& omp_priv = ~ 0 omp_out &= omp_in
| omp_priv = 0 omp_out |= omp_in
^ omp_priv = 0 omp_out ^= omp_in
&& omp_priv = 1 omp_out = omp_in && omp_out
|| omp_priv = 0 omp_out = omp_in || omp_out
max omp_priv = Minimal representable number in the reduction list item type omp_out = omp_in > omp_out ? omp_in : omp_out
min omp_priv = Maximal representable number in the reduction list item type omp_out = omp_in < omp_out ? omp_in : omp_out



SVG-Viewer needed.

SVG-Viewer needed.

Table 2.12 lists each reduction-identifier that is implicitly declared for numeric and logical types and its semantic initializer value. The actual initializer value is that value as expressed in the data type of the reduction list item.

Table 2.12: Implicitly Declared Fortran reduction-identifiers



Identifier Initializer Combiner



+ omp_priv = 0 omp_out = omp_in + omp_out
- omp_priv = 0 omp_out = omp_in + omp_out
* omp_priv = 1 omp_out = omp_in * omp_out
.and. omp_priv = .true. omp_out = omp_in .and. omp_out
.or. omp_priv = .false. omp_out = omp_in .or. omp_out
.eqv. omp_priv = .true. omp_out = omp_in .eqv. omp_out
.neqv. omp_priv = .false. omp_out = omp_in .neqv. omp_out
max omp_priv = Minimal representable number in the reduction list item type omp_out = max(omp_in, omp_out)
min omp_priv = Maximal representable number in the reduction list item type omp_out = min(omp_in, omp_out)
iand omp_priv = All bits on omp_out = iand(omp_in, omp_out)
ior omp_priv = 0 omp_out = ior(omp_in, omp_out)
ieor omp_priv = 0 omp_out = ieor(omp_in, omp_out)



SVG-Viewer needed.

In the above tables, omp_in and omp_out correspond to two identifiers that refer to storage of the type of the list item. If the list item is an array or array section, the identifiers to which omp_in and omp_out correspond each refer to an array element. omp_out holds the final value of the combiner operation. Any reduction-identifier that is defined with the declare reduction directive is also valid. In that case, the initializer and combiner of the reduction-identifier are specified by the initializer-clause and the combiner in the declare reduction directive.

Description A reduction clause specifies a reduction-identifier and one or more list items.

The reduction-identifier specified in a reduction clause must match a previously declared reduction-identifier of the same name and type for each of the list items. This match is done by means of a name lookup in the base language.

The list items that appear in a reduction clause may include array sections.

SVG-Viewer needed.

If the type is a derived class, then any reduction-identifier that matches its base classes is also a match, if no specific match for the type has been specified.

If the reduction-identifier is not an id-expression, then it is implicitly converted to one by prepending the keyword operator (for example, + becomes operator+).

If the reduction-identifier is qualified then a qualified name lookup is used to find the declaration.

If the reduction-identifier is unqualified then an argument-dependent name lookup must be performed using the type of each list item.

SVG-Viewer needed.

If a list item is an array or array section, it will be treated as if a reduction clause would be applied to each separate element of the array section.

If a list item is an array section, the elements of any copy of the array section will be stored contiguously.

SVG-Viewer needed.

If the original list item has the POINTER attribute, any copies of the list item are associated with private targets.

SVG-Viewer needed.

Any copies of a list item associated with the reduction are initialized with the initializer value of the reduction-identifier.

Any copies are combined using the combiner associated with the reduction-identifier.

Execution Model Events The reduction-begin event occurs before a task begins to perform loads and stores that belong to the implementation of a reduction and the reduction-end event occurs after the task has completed loads and stores associated with the reduction. If a task participates in multiple reductions, each reduction may be bracketed by its own pair of reduction-begin/reduction-end events or multiple reductions may be bracketed by a single pair of events. The interval defined by a pair of reduction-begin/reduction-end events may not contain a task scheduling point.

Tool Callbacks A thread dispatches a registered ompt_callback_reduction with ompt_sync_region_reduction in its kind argument and ompt_scope_begin as its endpoint argument for each occurrence of a reduction-begin event in that thread. Similarly, a thread dispatches a registered ompt_callback_reduction with ompt_sync_region_reduction in its kind argument and ompt_scope_end as its endpoint argument for each occurrence of a reduction-end event in that thread. These callbacks occur in the context of the task that performs the reduction and has the type signature ompt_callback_sync_region_t.

Restrictions Restrictions common to reduction clauses are as follows:

Cross References

2.21.5.2 Reduction Scoping Clauses

Reduction scoping clauses define the region in which a reduction is computed by tasks or SIMD lanes. All properties common to all reduction clauses, which are defined in Section 2.21.5.1, apply to reduction scoping clauses.

The number of copies created for each list item and the time at which those copies are initialized are determined by the particular reduction scoping clause that appears on the construct.

The time at which the original list item contains the result of the reduction is determined by the particular reduction scoping clause.

The location in the OpenMP program at which values are combined and the order in which values are combined are unspecified. Therefore, when comparing sequential and parallel executions, or when comparing one parallel execution to another (even if the number of threads used is the same), bitwise-identical results are not guaranteed to be obtained. Similarly, side effects (such as floating-point exceptions) may not be identical and may not take place at the same location in the OpenMP program.

To avoid data races, concurrent reads or updates of the original list item must be synchronized with the update of the original list item that occurs as a result of the reduction computation.

2.21.5.3 Reduction Participating Clauses

A reduction participating clause specifies a task or a SIMD lane as a participant in a reduction defined by a reduction scoping clause. All properties common to all reduction clauses, which are defined in Section 2.21.5.1, apply to reduction participating clauses.

Accesses to the original list item may be replaced by accesses to copies of the original list item created by a region that corresponds to a construct with a reduction scoping clause.

In any case, the final value of the reduction must be determined as if all tasks or SIMD lanes that participate in the reduction are executed sequentially in some arbitrary order.

2.21.5.4 reduction Clause

Summary The reduction clause specifies a reduction-identifier and one or more list items. For each list item, a private copy is created for each implicit task or SIMD lane and is initialized with the initializer value of the reduction-identifier. After the end of the region, the original list item is updated with the values of the private copies using the combiner associated with the reduction-identifier.

Syntax The syntax of the reduction clause is as follows:  

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

Where reduction-identifier is defined in Section 2.21.5.1, and reduction-modifier is one of the following:  

 
inscan 
task 
default  

Description The reduction clause is a reduction scoping clause and a reduction participating clause, as described in Section 2.21.5.2 and Section 2.21.5.3.

If reduction-modifier is not present or the defaultreduction-modifier is present, the behavior is as follows. For parallel, scope and worksharing constructs, one or more private copies of each list item are created for each implicit task, as if the private clause had been used. For the simd construct, one or more private copies of each list item are created for each SIMD lane, as if the private clause had been used. For the taskloop construct, private copies are created according to the rules of the reduction scoping clauses. For the teams construct, one or more private copies of each list item are created for the initial task of each team in the league, as if the private clause had been used. For the loop construct, private copies are created and used in the construct according to the description and restrictions in Section 2.21.3. At the end of a region that corresponds to a construct for which the reduction clause was specified, the original list item is updated by combining its original value with the final value of each of the private copies, using the combiner of the specified reduction-identifier.

If the inscanreduction-modifier is present, a scan computation is performed over updates to the list item performed in each logical iteration of the loop associated with the worksharing-loop, worksharing-loop SIMD, or simd construct (see Section 2.11.8). The list items are privatized in the construct according to the description and restrictions in Section 2.21.3. At the end of the region, each original list item is assigned the value described in Section 2.11.8.

If the taskreduction-modifier is present for a parallel, scope, or worksharing construct, then each list item is privatized according to the description and restrictions in Section 2.21.3, and an unspecified number of additional private copies may be created to support task reductions. Any copies associated with the reduction are initialized before they are accessed by the tasks that participate in the reduction, which include all implicit tasks in the corresponding region and all participating explicit tasks that specify an in_reduction clause (see Section 2.21.5.6). After the end of the region, the original list item contains the result of the reduction.

If nowait is not specified for the construct, the reduction computation will be complete at the end of the region that corresponds to the construct; however, if the reduction clause is used on a construct to which nowait is also applied, accesses to the original list item will create a race and, thus, have unspecified effect unless synchronization ensures that they occur after all threads have executed all of their iterations or section constructs, and the reduction computation has completed and stored the computed value of that list item. This can be ensured simply through a barrier synchronization in most cases.

Restrictions Restrictions to the reduction clause are as follows:

Cross References

2.21.5.5 task_reduction Clause

Summary The task_reduction clause specifies a reduction among tasks.

Syntax The syntax of the task_reduction clause is as follows:  

 
task_reduction(reduction-identifier : list)  

where reduction-identifier is defined in Section 2.21.5.1.

Description The task_reduction clause is a reduction scoping clause, as described in 2.21.5.2.

For each list item, the number of copies is unspecified. Any copies associated with the reduction are initialized before they are accessed by the tasks that participate in the reduction. After the end of the region, the original list item contains the result of the reduction.

Restrictions Restrictions to the task_reduction clause are as follows:

2.21.5.6 in_reduction Clause

Summary The in_reduction clause specifies that a task participates in a reduction.

Syntax The syntax of the in_reduction clause is as follows:  

 
in_reduction(reduction-identifier : list)  

where reduction-identifier is defined in Section 2.21.5.1.

Description The in_reduction clause is a reduction participating clause, as described in Section 2.21.5.3. For a given list item, the in_reduction clause defines a task to be a participant in a task reduction that is defined by an enclosing region for a matching list item that appears in a task_reduction clause or a reduction clause with task as the reduction-modifier, where either:

1.
The matching list item has the same storage location as the list item in the in_reduction clause; or
2.
A private copy, derived from the matching list item, that is used to perform the task reduction has the same storage location as the list item in the in_reduction clause.

For the task construct, the generated task becomes the participating task. For each list item, a private copy may be created as if the private clause had been used.

For the target construct, the target task becomes the participating task. For each list item, a private copy may be created in the data environment of the target task as if the private clause had been used. This private copy will be implicitly mapped into the device data environment of the target device, if the target device is not the parent device.

At the end of the task region, if a private copy was created its value is combined with a copy created by a reduction scoping clause or with the original list item.

Restrictions Restrictions to the in_reduction clause are as follows:

2.21.5.7 declare reduction Directive

Summary The following section describes the directive for declaring user-defined reductions. The declare reduction directive declares a reduction-identifier that can be used in a reduction clause. The declare reduction directive is a declarative directive.

Syntax

SVG-Viewer needed.

The syntax of the declare reduction directive is as follows:  

 
#pragma omp declare reduction(reduction-identifier : typename-list : 
combiner )[initializer-clause] new-line  

where:

SVG-Viewer needed.

SVG-Viewer needed.

The syntax of the declare reduction directive is as follows:  

 
#pragma omp declare reduction(reduction-identifier : typename-list : 
combiner) [initializer-clause] new-line  

where:

SVG-Viewer needed.

SVG-Viewer needed.

The syntax of the declare reduction directive is as follows:  

 
!$omp declare reduction(reduction-identifier : type-list : combiner) 
[initializer-clause]  

where:

SVG-Viewer needed.

Description User-defined reductions can be defined using the declare reduction directive. The reduction-identifier and the type identify the declare reduction directive. The reduction-identifier can later be used in a reduction clause that uses variables of the type or types specified in the declare reduction directive. If the directive specifies several types then the behavior is as if a declare reduction directive was specified for each type.

SVG-Viewer needed.

If a type with deferred or assumed length type parameter is specified in a declare reduction directive, the reduction-identifier of that directive can be used in a reduction clause with any variable of the same type and the same kind parameter, regardless of the length type Fortran parameters with which the variable is declared.

SVG-Viewer needed.

The visibility and accessibility of a user-defined reduction are the same as those of a variable declared at the same location in the program. The enclosing context of the combiner and of the initializer-expr is that of the declare reduction directive. The combiner and the initializer-expr must be correct in the base language as if they were the body of a function defined at the same location in the program.

SVG-Viewer needed.

If the reduction-identifier is the same as the name of a user-defined operator or an extended operator, or the same as a generic name that is one of the allowed intrinsic procedures, and if the operator or procedure name appears in an accessibility statement in the same module, the accessibility of the corresponding declare reduction directive is determined by the accessibility attribute of the statement.

If the reduction-identifier is the same as a generic name that is one of the allowed intrinsic procedures and is accessible, and if it has the same name as a derived type in the same module, the accessibility of the corresponding declare reduction directive is determined by the accessibility of the generic name according to the base language.

SVG-Viewer needed.

SVG-Viewer needed.

The declare reduction directive can also appear at the locations in a program where a static data member could be declared. In this case, the visibility and accessibility of the declaration are the same as those of a static data member declared at the same location in the program.

SVG-Viewer needed.

The combiner specifies how partial results are combined into a single value. The combiner can use the special variable identifiers omp_in and omp_out that are of the type of the variables that this reduction-identifier reduces. Each of the two special variable identifiers denotes one of the values to be combined before executing the combiner. The special omp_out identifier refers to the storage that holds the resulting combined value after executing the combiner.

The number of times that the combiner is executed and the order of these executions for any reduction clause are unspecified.

SVG-Viewer needed.

If the combiner is a subroutine name with an argument list, the combiner is evaluated by calling the subroutine with the specified argument list.

If the combiner is an assignment statement, the combiner is evaluated by executing the assignment statement.

If a generic name is used in the combiner expression and the list item in the corresponding reduction clause is an array or array section, it is resolved to the specific procedure that is elemental or only has scalar dummy arguments.

SVG-Viewer needed.

If the initializer-expr value of a user-defined reduction is not known a priori, the initializer-clause can be used to specify one. The content of the initializer-clause will be used as the initializer for the private copies of reduction list items where the omp_priv identifier will refer to the storage to be initialized. The special identifier omp_orig can also appear in the initializer-clause and it will refer to the storage of the original variable to be reduced.

The number of times that the initializer-expr is evaluated and the order of these evaluations are unspecified.

SVG-Viewer needed.

If the initializer-expr is a function name with an argument list, the initializer-expr is evaluated by calling the function with the specified argument list. Otherwise, the initializer-expr specifies how omp_priv is declared and initialized.

SVG-Viewer needed.

SVG-Viewer needed.

If no initializer-clause is specified, the private variables will be initialized following the rules for initialization of objects with static storage duration.

SVG-Viewer needed.

SVG-Viewer needed.

If no initializer-expr is specified, the private variables will be initialized following the rules for default-initialization.

SVG-Viewer needed.

SVG-Viewer needed.

If the initializer-expr is a subroutine name with an argument list, the initializer-expr is evaluated by calling the subroutine with the specified argument list.

If the initializer-expr is an assignment statement, the initializer-expr is evaluated by executing the assignment statement.

If no initializer-clause is specified, the private variables will be initialized as follows:

SVG-Viewer needed.

SVG-Viewer needed.

If reduction-identifier is used in a target region then a declare target directive must be specified for any function that can be accessed through the combiner and initializer-expr.

SVG-Viewer needed.

SVG-Viewer needed.

If reduction-identifier is used in a target region then a declare target directive must be specified for any function or subroutine that can be accessed through the combiner and initializer-expr.

SVG-Viewer needed.

Restrictions Restrictions to the declare reduction directive are as follows:

Cross References