KokkosBatched::Identity¶
Defined in header: KokkosBatched_Identity.hpp
class Identity {
public:
// Constructor
KOKKOS_INLINE_FUNCTION
Identity();
// Destructor
KOKKOS_INLINE_FUNCTION
~Identity();
// Apply identity operator with team parallelism
template <typename ArgTrans, typename ArgMode, int sameXY,
typename MemberType, typename XViewType, typename YViewType>
KOKKOS_INLINE_FUNCTION
void apply(const MemberType& member,
const XViewType& X,
const YViewType& Y) const;
// Apply identity operator (serial version)
template <typename ArgTrans, int sameXY,
typename XViewType, typename YViewType>
KOKKOS_INLINE_FUNCTION
void apply(const XViewType& X,
const YViewType& Y) const;
};
The Identity
class implements an identity operator that simply copies the input to the output. It’s particularly useful as a “no-op” preconditioner in iterative solvers or as a placeholder when testing different operator configurations.
Mathematically, the identity operator \(I\) applied to a vector \(x\) simply returns the same vector:
In the context of batched operations, the class efficiently copies batched vectors without additional computations.
Parameters¶
Method Parameters (apply)¶
- member:
Team execution policy instance (only for team version)
- X:
Input vector view
- Y:
Output vector view
Template Parameters¶
ArgTrans
specifies the transposition mode (typically NoTranspose)ArgMode
must be one of:KokkosBatched::Mode::Serial
for serial executionKokkosBatched::Mode::Team
for team-based executionKokkosBatched::Mode::TeamVector
for team-vector-based execution
sameXY
is a flag that optimizes when X and Y are the same view (0 = different, 1 = same)MemberType
must be a Kokkos TeamPolicy member typeXViewType
andYViewType
must be views representing vectorsAll views must be accessible in the execution space
Example¶
#include <Kokkos_Core.hpp>
#include <KokkosBatched_Identity.hpp>
using execution_space = Kokkos::DefaultExecutionSpace;
using memory_space = execution_space::memory_space;
// Scalar type to use
using scalar_type = double;
int main(int argc, char* argv[]) {
Kokkos::initialize(argc, argv);
{
// Vector dimensions
int batch_size = 10; // Number of vectors
int n = 100; // Vector length
// Create input and output vectors
Kokkos::View<scalar_type**, Kokkos::LayoutRight, memory_space>
x("x", batch_size, n);
Kokkos::View<scalar_type**, Kokkos::LayoutRight, memory_space>
y("y", batch_size, n);
// Initialize x on host with some values
auto x_host = Kokkos::create_mirror_view(x);
for (int b = 0; b < batch_size; ++b) {
for (int i = 0; i < n; ++i) {
x_host(b, i) = b * 100 + i; // Unique value per element
}
}
// Copy to device
Kokkos::deep_copy(x, x_host);
// Create identity operator
KokkosBatched::Identity identity_op;
// Create team policy
using policy_type = Kokkos::TeamPolicy<execution_space>;
int team_size = policy_type::team_size_recommended(
[](const int &, const int &) {},
Kokkos::ParallelForTag());
policy_type policy(batch_size, team_size);
// Apply identity operator to copy x to y using team parallelism
Kokkos::parallel_for("IdentityOperator", policy,
KOKKOS_LAMBDA(const typename policy_type::member_type& member) {
const int b = member.league_rank();
// Get current batch's vectors
auto x_b = Kokkos::subview(x, b, Kokkos::ALL());
auto y_b = Kokkos::subview(y, b, Kokkos::ALL());
// Apply identity operator: y = x
// sameXY = 0 indicates x and y are different views
identity_op.template apply<KokkosBatched::Trans::NoTranspose,
KokkosBatched::Mode::TeamVector, 0>
(member, x_b, y_b);
}
);
// Copy results back to host
auto y_host = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), y);
// Verify that y contains the same values as x
bool test_passed = true;
for (int b = 0; b < batch_size; ++b) {
for (int i = 0; i < n; ++i) {
if (x_host(b, i) != y_host(b, i)) {
test_passed = false;
std::cout << "Mismatch at batch " << b << ", index " << i << ": "
<< x_host(b, i) << " vs " << y_host(b, i) << std::endl;
break;
}
}
if (!test_passed) break;
}
if (test_passed) {
std::cout << "Identity operator test: PASSED" << std::endl;
// Print first few values from the first batch
std::cout << "First batch values: [";
for (int i = 0; i < std::min(n, 5); ++i) {
std::cout << y_host(0, i) << " ";
}
std::cout << "...]" << std::endl;
} else {
std::cout << "Identity operator test: FAILED" << std::endl;
}
// Demonstrate using Identity as a preconditioner
std::cout << "\nDemonstrating Identity as a 'no-op' preconditioner:" << std::endl;
// Reset y
Kokkos::deep_copy(y, 0);
// Create a simple preconditioned system using Identity
// In a real application, you would use a more effective preconditioner
Kokkos::parallel_for("PreconditionedSystem", policy,
KOKKOS_LAMBDA(const typename policy_type::member_type& member) {
const int b = member.league_rank();
// Get vectors for this batch
auto x_b = Kokkos::subview(x, b, Kokkos::ALL());
auto y_b = Kokkos::subview(y, b, Kokkos::ALL());
// Apply "preconditioning" (which doesn't change anything)
identity_op.template apply<KokkosBatched::Trans::NoTranspose,
KokkosBatched::Mode::TeamVector, 0>
(member, x_b, y_b);
}
);
// Copy results back to host
Kokkos::deep_copy(y_host, y);
// Verify again
test_passed = true;
for (int b = 0; b < batch_size; ++b) {
for (int i = 0; i < n; ++i) {
if (x_host(b, i) != y_host(b, i)) {
test_passed = false;
break;
}
}
if (!test_passed) break;
}
if (test_passed) {
std::cout << "Identity as preconditioner: PASSED" << std::endl;
} else {
std::cout << "Identity as preconditioner: FAILED" << std::endl;
}
}
Kokkos::finalize();
return 0;
}
Using with Krylov Solvers¶
// Example of using Identity as a preconditioner with CG
// Note: This is a simplified code snippet showing the pattern
// Create operators
matrix_operator_type A_op(values, row_ptr, col_idx);
KokkosBatched::Identity I_op;
// Create solver handle
krylov_handle_type handle(batch_size, n_team);
handle.set_max_iteration(100);
handle.set_tolerance(1e-8);
// Solve with "no preconditioning" (identity preconditioner)
Kokkos::parallel_for("UnpreconditionedCG", policy,
KOKKOS_LAMBDA(const typename policy_type::member_type& member) {
const int b = member.league_rank();
auto B_b = Kokkos::subview(B, b, Kokkos::ALL());
auto X_b = Kokkos::subview(X, b, Kokkos::ALL());
// Solve using CG without effective preconditioning
KokkosBatched::CG<typename policy_type::member_type,
KokkosBatched::Mode::TeamVector>
::invoke(member, A_op, B_b, X_b, handle);
}
);