KaMPIng 0.2.1
(Near) zero-overhead MPI wrapper for C++
Loading...
Searching...
No Matches
kamping-types

kamping-types

A standalone C++17 header-only library that maps C++ types to MPI datatypes and reduction operations.

kamping-types is extracted from KaMPIng and can be consumed independently — without the KaMPIng communicator layer.

Quick Start

include(FetchContent)
FetchContent_Declare(
kamping
GIT_REPOSITORY https://github.com/kamping-site/kamping.git
GIT_TAG main
)
FetchContent_MakeAvailable(kamping)
# Link only to the type module, not the full KaMPIng library
target_link_libraries(myapp PRIVATE kamping::types)

Then include what you need:

// Obtain an MPI_Datatype for a builtin — no commit required
MPI_Datatype int_type = kamping::types::mpi_type_traits<int>::data_type(); // MPI_INT
// Commit and RAII-manage a contiguous type for float[4]
MPI_Send(data, 1, arr_type.data_type(), dest, tag, MPI_COMM_WORLD);
// type is freed when arr_type goes out of scope
RAII wrapper that commits an MPI_Datatype on construction and frees it on destruction.
Definition scoped_datatype.hpp:33
Type traits and dispatcher for mapping C++ types to MPI datatypes.
RAII wrapper that commits an MPI_Datatype on construction and frees it on destruction.
Struct-like MPI type construction via field reflection.
The type trait that maps a C++ type T to an MPI_Datatype for the kamping-types module.
Definition mpi_type_traits.hpp:89

CMake Options

Option Default Description
KAMPING_TYPES_BUILD_EXAMPLES ON (top-level), OFF (subdirectory) Build the example program
KAMPING_TYPES_ENABLE_REFLECTION OFF Enable struct reflection via Boost.PFR for arbitrary struct types

Headers

Core

Header Contents
kamping/types/builtin_types.hpp TypeCategory, builtin_type<T>, is_builtin_type_v<T>
kamping/types/mpi_type_traits.hpp type_dispatcher<T>(), mpi_type_traits<T>, has_static_type_v<T>
kamping/types/contiguous_type.hpp contiguous_type<T,N>, byte_serialized<T>
kamping/types/struct_type.hpp kamping_tag, struct_type<T>
kamping/types/scoped_datatype.hpp ScopedDatatype — RAII commit/free wrapper
kamping/types/kabool.hpp kabool — bool wrapper safe for MPI containers
kamping/types/reduce_ops.hpp kamping::ops:: functors, mpi_operation_traits<Op,T>, ScopedOp, with_operation_functor

Opt-in standard library specializations (kamping/types/std/)

These headers register standard library types with mpi_type_traits. Include only what you need; the safe and unsafe variants for the same type are mutually exclusive.

Header Type How
kamping/types/std/utility.hpp std::pair<F,S> struct_type — models field layout; field types must have a static MPI type
kamping/types/std/tuple.hpp std::tuple<Ts...> struct_type — models field layout; all element types must have a static MPI type
kamping/types/std/unsafe/utility.hpp std::pair<F,S> byte_serialized — flat byte copy; ignores padding
kamping/types/std/unsafe/tuple.hpp std::tuple<Ts...> byte_serialized — flat byte copy; ignores padding
kamping/types/std/unsafe/trivially_copyable.hpp any std::is_trivially_copyable<T> not already registered byte_serialized — catch-all; excludes std::pair/std::tuple so it composes with the above

Type Dispatch Rules

type_dispatcher<T>() maps C++ types to type traits according to these rules:

C++ type Result
MPI builtin (int, double, std::complex<float>, …) builtin_type<T> — named MPI type, no commit
Enum dispatches to underlying type
T[N], std::array<T,N> contiguous_type<T,N> — must be committed
Everything else no_matching_type — specialize mpi_type_traits<T>

Use has_static_type_v<T> to check at compile time whether a type is handled.

Extending for Custom Types

For std::pair and std::tuple, include the ready-made headers from kamping/types/std/:

#include "kamping/types/std/utility.hpp" // std::pair via struct_type (safe)
#include "kamping/types/std/tuple.hpp" // std::tuple via struct_type (safe)
static_assert(kamping::types::has_static_type_v<std::pair<int, double>>); // true

For your own types, specialize mpi_type_traits<T> directly:

struct Particle { float position[3]; double mass; };
struct Point { float x, y, z; }; // tightly packed — byte serialization is safe
namespace kamping::types {
// Option 1: struct_type — correct field-aware layout (requires Boost.PFR or std::pair/tuple)
template <>
struct mpi_type_traits<Particle> : struct_type<Particle> {};
// Option 2: byte_serialized — flat byte copy; only correct when there is no padding
template <>
struct mpi_type_traits<Point> : byte_serialized<Point> {};
// Option 3: build the MPI_Datatype manually for full control
template <>
struct mpi_type_traits<Point> {
static constexpr bool has_to_be_committed = true;
static MPI_Datatype data_type() {
MPI_Datatype type;
MPI_Type_contiguous(3, MPI_FLOAT, &type);
return type;
}
};
} // namespace kamping::types
types::struct_type< T, kamping_lookup > struct_type
Constructs an MPI struct type for T, using kamping_lookup to resolve field types (includes the byte-s...
Definition mpi_datatype.hpp:180

To register all trivially copyable types at once, include the catch-all:

#include "kamping/types/std/unsafe/trivially_copyable.hpp"
struct Point { float x, y, z; };
static_assert(kamping::types::has_static_type_v<Point>); // true — registered automatically

Reduction Operations

kamping/types/reduce_ops.hpp provides a C++ functor vocabulary that maps to MPI's builtin reduction ops.

Builtin Functor Types (kamping::ops::)

Functor MPI constant Identity
ops::max<T> MPI_MAX std::numeric_limits<T>::lowest()
ops::min<T> MPI_MIN std::numeric_limits<T>::max()
ops::plus<T> MPI_SUM 0
ops::multiplies<T> MPI_PROD 1
ops::logical_and<T> MPI_LAND true
ops::logical_or<T> MPI_LOR false
ops::logical_xor<T> MPI_LXOR false
ops::bit_and<T> MPI_BAND ~T{0}
ops::bit_or<T> MPI_BOR T{0}
ops::bit_xor<T> MPI_BXOR T{0}

All functors default to T = void, enabling deduced argument types.

Querying the MPI_Op at Compile Time

mpi_operation_traits<Op, T> maps a (functor, element type) pair to its builtin MPI_Op:

using T = mpi_operation_traits<kamping::ops::plus<>, int>;
static_assert(T::is_builtin); // true — maps to MPI_SUM
MPI_Op op = T::op(); // MPI_SUM
int identity = T::identity; // 0
MPI reduction operation functor vocabulary, type traits, and RAII handle.

is_builtin is false for functors not covered by a predefined MPI operation (e.g., std::minus<>).

RAII Handle: ScopedOp

ScopedOp wraps an MPI_Op and calls MPI_Op_free on destruction only when it owns the op (user-defined ops created via MPI_Op_create). Predefined constants are wrapped non-owning.

Analogous to ScopedDatatype for MPI_Datatype.

MPI_Op raw_op;
MPI_Op_create(&my_reduce_fn, /*commute=*/1, &raw_op);
kamping::types::ScopedOp scoped{raw_op, /*owns=*/true};
// MPI_Op_free called automatically when scoped goes out of scope
RAII wrapper for an MPI_Op.
Definition reduce_ops.hpp:378

Runtime Dispatch: with_operation_functor

with_operation_functor maps a runtime MPI_Op handle to its C++ functor and invokes a callable:

kamping::types::with_operation_functor(MPI_SUM, [](auto op) {
// op is kamping::ops::plus<>{}
});

Unknown ops dispatch to kamping::ops::null<>{}.

Commutativity Tags

User-defined operations can be tagged:

kamping::ops::commutative // ops::internal::commutative_tag
kamping::ops::non_commutative // ops::internal::non_commutative_tag