Skip to content

kamping-site/kamping-v2

Repository files navigation

GitHub

KaMPIng v2

KaMPIng v2 is a next-generation C++20 MPI wrapper built around a concept-based buffer protocol and composable range adaptors. Instead of wrapping arguments in named-parameter factories, callers pipe standard C++ objects through std::ranges-style view chains that attach MPI metadata (element count, MPI datatype, per-rank counts, displacements). The resulting view satisfies one of the buffer concepts and is passed directly to a free-function MPI wrapper.

// Simple point-to-point
kamping::v2::send(data, 1, comm);
kamping::v2::recv(data | kamping::views::resize, comm);

// Variadic collective with automatic counts/displacements
kamping::v2::alltoallv(send_buf | kamping::views::with_counts(scounts),
                       kamping::v2::auto_recv_v<int>(),
                       comm);

// Non-blocking with automatic resize
auto req = kamping::v2::irecv(buf | kamping::views::resize, comm);
// ... other work ...
auto result = req.wait();

Repository layout

Component Description C++ standard CMake target
mpi-core/ Low-level MPI wrappers. Buffer concepts and accessor dispatch (mpi::experimental::). C++20 mpi::core
kamping-v2/ High-level wrappers with ownership, infer, resize, auto-counts/displs (kamping::v2::). C++20 kamping::v2
ecosystem/cereal/ Cereal serialization adapter. C++20 kamping::ecosystem::cereal
ecosystem/kokkos/ Kokkos view adapter (device-aware MPI via buffer_traits). C++20 kamping::ecosystem::kokkos
ecosystem/sycl/ SYCL accessor adapter via sycl_view (Intel oneAPI DPC++ only). C++20 kamping::ecosystem::sycl
ecosystem/thrust/ Thrust device_vector adapter for CUDA-aware MPI. C++20 kamping::ecosystem::thrust

kamping-types (MPI datatype registry, kamping::types) is consumed from the kamping-site/kamping repository via FetchContent.

Quick Start

Using kamping-v2 via FetchContent

include(FetchContent)
FetchContent_Declare(
    kamping_v2
    GIT_REPOSITORY https://github.com/kamping-site/kamping-v2.git
    GIT_TAG main
)
FetchContent_MakeAvailable(kamping_v2)
target_link_libraries(myapp PRIVATE kamping::v2)

Using only mpi-core via FetchContent

include(FetchContent)
FetchContent_Declare(
    kamping_v2
    GIT_REPOSITORY https://github.com/kamping-site/kamping-v2.git
    GIT_TAG main
    SOURCE_SUBDIR mpi-core
)
FetchContent_MakeAvailable(kamping_v2)
target_link_libraries(myapp PRIVATE mpi::core)

Supported Operations

Collectives: allgather, allgatherv, allreduce, alltoall, alltoallv, barrier, bcast, exscan, gather, gatherv, reduce, scan, scatter, scatterv

Point-to-point: send, recv, sendrecv, isend, irecv, isendrecv

Building

Requires CMake 3.25+, a C++20 compiler, and an MPI installation.

# Configure (builds tests and examples)
cmake --preset debug    # or: release, relwithdeb

# Build
cmake --build --preset debug --parallel

# Test
ctest --preset debug

Key CMake options:

Option Default Description
KAMPING_BUILD_EXAMPLES_AND_TESTS OFF Build tests and examples
KAMPING_WARNINGS_ARE_ERRORS OFF Treat warnings as errors
KAMPING_ENABLE_SERIALIZATION OFF Build the Cereal ecosystem adapter
KAMPING_ENABLE_KOKKOS OFF Build the Kokkos ecosystem adapter
KAMPING_ENABLE_REFLECTION ON Enable Boost.PFR struct reflection in kamping-types

Buffer Protocol

Any type satisfying the buffer concepts can be passed to MPI wrappers — no inheritance required. Accessor dispatch follows a three-tier priority:

  1. mpi::experimental::buffer_traits<T> specialization (non-intrusive, for types you don't own)
  2. t.mpi_count() / t.mpi_ptr() / t.mpi_type() member functions
  3. std::ranges::size / std::ranges::data + builtin MPI type deduction
// Adapt any third-party type non-intrusively:
template <>
struct mpi::experimental::buffer_traits<MyType> {
    static std::ptrdiff_t count(MyType const& t) { return 1; }
    static int const*     ptr(MyType const& t)   { return &t.val; }
    static int*           ptr(MyType& t)         { return &t.val; }
    static MPI_Datatype   type(MyType const&)    { return MPI_INT; }
};

View Adaptors

All views are composable with | and lazy:

View factory Effect
views::resize Marks a container as resizable; MPI recv resizes before writing
views::with_type(dt) Overrides the MPI datatype
views::with_size(n) Overrides element count
views::with_counts(range) Attaches per-rank send/recv counts (variadic operations)
views::with_displs(range) Attaches per-rank displacements
views::auto_displs([resize,] [container]) Computes displacements via exclusive_scan of counts; pass resize tag to auto-resize the displacement buffer, container to use custom storage (default std::vector<int>)
views::resize_v Variadic recv buffer: resizes from counts+displs before receive
views::auto_counts([buf]) Deferred variadic counts buffer
views::auto_recv_v Shorthand for auto_counts() | auto_displs() | resize_v
views::ref_single(val) Wraps a single scalar as a one-element contiguous buffer
views::serialize / views::deserialize<T>() Cereal serialization (ecosystem/cereal)

Non-Blocking Operations

Non-blocking calls return iresult<Buf> — a move-only handle that stores the buffer on the heap so the pointer captured by MPI stays stable. The destructor calls MPI_Wait if not already completed.

auto req = kamping::v2::isend(data, 1, comm);
// ... other work ...
req.wait();

auto req2 = kamping::v2::irecv(buf | kamping::views::resize, comm);
auto result = req2.wait();  // returns the resized buffer

// Poll without blocking: bool for borrowed buffers, std::optional<T> for owned
if (auto r = req2.test()) { /* completed */ }

Relation to KaMPIng v1

The original KaMPIng (named-parameter / template-metaprogramming API, C++17) lives in kamping-site/kamping. v1 and v2 share the kamping-types type-registry library (maintained in the v1 repo). The two APIs are independent and can coexist in the same binary.

License

KaMPIng-v2 is released under the Boost Software License 1.0. See LICENSE for details.

About

KaMPIng v2 — concept-based C++20 MPI bindings

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages