reduction_identity
¶
Defined in header <Kokkos_Core.hpp>
-
template<typename ScalarType>
struct reduction_identity¶ The
reduction_identity
class template provides static member functions that return the identity value for various reduction types.Static members available for integral and floating-point types:
-
KOKKOS_FUNCTION static ScalarType sum()¶
- Returns:
Neutral element for built-in reducer
Sum
-
KOKKOS_FUNCTION static ScalarType prod()¶
- Returns:
Neutral element for built-in reducer
Prod
-
KOKKOS_FUNCTION static ScalarType min()¶
- Returns:
Neutral element for built-in reducer
Min
-
KOKKOS_FUNCTION static ScalarType max()¶
- Returns:
Neutral element for built-in reducer
Max
Static members available for integral types:
-
KOKKOS_FUNCTION static ScalarType land()¶
- Returns:
Neutral element for built-in reducer
LAnd
(Logical AND)
-
KOKKOS_FUNCTION static ScalarType lor()¶
- Returns:
Neutral element for built-in reducer
LOr
(Logical OR)
-
KOKKOS_FUNCTION static ScalarType band()¶
- Returns:
Neutral element for built-in reducer
BAnd
(Bitwise AND)
-
KOKKOS_FUNCTION static ScalarType bor()¶
- Returns:
Neutral element for built-in reducer
BOr
(Bitwise OR)
-
KOKKOS_FUNCTION static ScalarType sum()¶
Description¶
The reduction_identity
struct provides the identity element (also known as
the neutral element) for various common reduction operations. In the context of
a parallel reduction, the identity element is the starting value for the
reduction variable on each thread. When combined with any other value using the
reduction operation, it does not change the other value. For example, for a sum
reduction, the identity is \(0\), because \(x+0=x\). For a product
reduction, the identity is \(1\), because \(x \times 1 = x\).
Kokkos’ built-in reducers (e.g., Sum, Prod, Min,
Max) implicitly use specializations of reduction_identity
to
initialize the thread-local reduction accumulators.
Kokkos provides specializations for all arithmetic types (i.e. integral and
floating-point types) as well as for complex<T>
.
Note
Kokkos::reduction_identity
is not intended for direct use in your
application code. Instead, it serves as a customization point within the
Kokkos framework. You should only specialize reduction_identity when you
need to enable Kokkos’s built-in reducers (like Kokkos::Sum
,
Kokkos::Min
, Kokkos::Max
, etc.) to work seamlessly with your own
user-defined data types. This allows Kokkos to correctly determine the
initial “identity” value for your custom type during parallel reduction
operations.
Custom Scalar Types¶
For custom (user-defined) ScalarType
s to be used with Kokkos’ built-in
reducers, a template specialization of
Kokkos::reduction_identity<CustomType>
must be defined. This
specialization must provide static member functions corresponding to the
desired reduction operations. These functions should return an instance of
CustomType
initialized with the appropriate identity value.
Example: Specializing reduction_identity
for a Custom Array Type¶
Consider a custom struct array_type
that holds an an array of integers, for
which we want to perform a sum reduction.
#include <Kokkos_Core.hpp>
namespace sample {
template <class ScalarType, int N>
struct array_type {
ScalarType the_array[N] = {};
KOKKOS_FUNCTION
array_type& operator+=(const array_type& src) {
for (int i = 0; i < N; ++i) {
the_array[i] += src.the_array[i];
}
return *this;
}
};
using ValueType = array_type<int, 4>;
} // namespace sample
// Specialization of Kokkos::reduction_identity for sample::ValueType
template <>
struct Kokkos::reduction_identity<sample::ValueType> {
KOKKOS_FUNCTION static sample::ValueType sum() {
return sample::ValueType(); // Default constructor initializes to zeros
}
// If other reduction types were needed (e.g., min, max, prod),
// their respective identity functions would also be defined here.
};
int main(int argc, char* argv[]) {
Kokkos::initialize(argc, argv);
{
const int E = 100;
sample::ValueType tr; // Result will be stored here
Kokkos::parallel_reduce(
"SumArray", E,
KOKKOS_LAMBDA(const int i, sample::ValueType& lval) {
lval.the_array[0] += 1;
lval.the_array[1] += i;
lval.the_array[2] += i * i;
lval.the_array[3] += i * i * i;
},
Kokkos::Sum<sample::ValueType>(tr));
printf("Computed result for %d is {%d, %d, %d, %d}\n", E,
tr.the_array[0], tr.the_array[1], tr.the_array[2],
tr.the_array[3]);
// Expected values:
// [0]: E = 100
// [1]: sum(0..99) = 99*100/2 = 4950
// [2]: sum(0..99) of i*i = 99*(99+1)*(2*99+1)/6 = 328350
// [3]: sum(0..99) of i*i*i = (99*100/2)^2 = 4950^2 = 24502500
printf("Expected result for %d is {%d, %d, %d, %d}\n", E,
100, 4950, 328350, 24502500);
}
Kokkos::finalize();
return 0;
}