Views¶
All views live in kamping::v2::views and compose with |. Each one can be called with the buffer as the first
argument or applied with |, like a std::ranges adaptor: views::with_counts(buf, counts) is the same as
buf | views::with_counts(counts). Views without arguments, such as views::resize, are applied without
parentheses. Buffers passed as lvalues are borrowed, rvalues are moved into the view.
Views are lazy: composing them allocates and computes nothing, and their metadata is computed on first access.
Getting the container back¶
Operations return the buffers they were given, so a buffer passed through views comes back as a view. Every view
has underlying(), which returns the container at the bottom of
the chain: moved out of an rvalue, by reference from an lvalue.
std::vector<int> data = v2::recv(std::vector<int>{} | views::resize, source, comm).underlying();
auto [_, recv] = v2::allgatherv(local, v2::auto_recv_v<int>(), comm);
std::vector<int>& all = recv.underlying();
Attaching metadata¶
-
auto with_type(MPI_Datatype type)¶
-
template<typename Buf>
auto with_type(Buf &&buf, MPI_Datatype type)¶ Overrides the MPI datatype:
buf | views::with_type(dt).Defined in header
<kamping/v2/views/with_type_view.hpp>
-
auto with_count(std::ptrdiff_t count)¶
-
template<typename Buf>
auto with_count(Buf &&buf, std::ptrdiff_t count)¶ Overrides the element count:
buf | views::with_count(n).Useful for non-range objects that expose mpi_ptr() but no size — compose with with_type to build a complete data_buffer. For limiting the element count of a range, prefer std::views::take.
Defined in header
<kamping/v2/views/with_count_view.hpp>
-
template<count_range Counts>
auto with_counts(Counts &&counts)¶ -
template<typename Buf, count_range Counts>
auto with_counts(Buf &&buf, Counts &&counts)¶ Attaches per-rank counts:
buf | views::with_counts(counts). The counts are borrowed if passed as lvalue.Defined in header
<kamping/v2/views/with_counts_view.hpp>Example:
std::vector<int> data = ..., counts = ...; auto send = data | views::with_counts(counts) | views::auto_displs; v2::alltoallv(send, v2::auto_recv_v<int>(), comm);
-
template<count_range Displs>
auto with_displs(Displs &&displs)¶ -
template<typename Buf, count_range Displs>
auto with_displs(Buf &&buf, Displs &&displs)¶ -
template<count_range Displs>
auto with_displs(monotonic_t, Displs &&displs)¶ -
template<typename Buf, count_range Displs>
auto with_displs(monotonic_t, Buf &&buf, Displs &&displs)¶ Attaches per-rank displacements:
buf | views::with_displs(displs), orbuf | views::with_displs(monotonic, displs)to declare them monotonically non-decreasing. The displacements are borrowed if passed as lvalue.Monotonic displacements let
views::resize_vsize the receive buffer in O(1), from the last displacement and count, instead of scanning all of them.Defined in header
<kamping/v2/views/with_displs_view.hpp>
-
auto auto_displs()¶
-
template<count_range Displs>
auto auto_displs(Displs &&displs)¶ -
template<typename Buf, count_range Displs>
auto auto_displs(Buf &&buf, Displs &&displs)¶ -
template<count_range Displs>
auto auto_displs(resize_t, Displs &&displs)¶ -
template<typename Buf, count_range Displs>
auto auto_displs(resize_t, Buf &&buf, Displs &&displs)¶ Attaches displacements computed from the buffer’s counts (exclusive prefix sum), lazily on first access:
buf | auto_displsorbuf | auto_displs(): stored in an ownedstd::vector<int>, resized as needed;buf | auto_displs(displs)orauto_displs(buf, displs): in the caller-provideddispls, which must already be large enough;buf | auto_displs(resize, displs)orauto_displs(resize, buf, displs): in the caller-provideddispls, resized as needed.
Defined in header
<kamping/v2/views/auto_displs_view.hpp>
Receive buffers that size themselves¶
-
template<typename Buf>
auto resize(Buf &&buf)¶ Resizes the wrapped container to fit the incoming data before receiving:
buf | views::resize.The operation determines the receive count (for point-to-point receives by probing the message) and passes it to
set_recv_count(n); the container is resized on first access to its data. Existing elements are kept. Takes no arguments, so it is applied without parentheses. Place it last in a pipeline:buf | views::with_type(t) | views::resize.Defined in header
<kamping/v2/views/resize_view.hpp>
-
auto auto_counts()¶
-
template<count_range Counts>
auto auto_counts(Counts &&counts)¶ -
template<count_range Counts>
auto auto_counts(resize_t, Counts &&counts)¶ Attaches deferred per-rank counts, which the operation exchanges (see
infer()):buf | auto_countsorbuf | auto_counts(): the counts are stored in an ownedstd::vector<int>, resized to the communicator size;buf | auto_counts(counts): in the caller-providedcounts, which must already have one entry per rank;buf | auto_counts(resize, counts): in the caller-providedcounts, resized to the communicator size.
Defined in header
<kamping/v2/views/auto_counts_view.hpp>
-
template<typename Buf>
auto resize_v(Buf &&buf)¶ Resizes a variable-size receive buffer to fit its counts and displacements before receiving:
buf | views::auto_counts | views::auto_displs | views::resize_v.The buffer must already provide per-rank counts and displacements, e.g. via
auto_counts | auto_displsorwith_counts | with_displs. The container is resized on first access to its data, once the counts are known; with monotonic displacements in O(1). Takes no arguments, so it is applied without parentheses.Defined in header
<kamping/v2/views/resize_v_view.hpp>
-
template<typename Buf>
auto auto_recv_v(Buf &&buf)¶ Makes a variable-size receive buffer that sizes itself:
buf | views::auto_recv_vis shorthand forbuf | views::auto_counts | views::auto_displs | views::resize_v.The operation exchanges the per-rank counts, the displacements are computed from them, and the container is resized to fit before receiving. For a fresh, owned buffer use the factory
kamping::v2::auto_recv_v<T>().Defined in header
<kamping/v2/views/auto_recv_v.hpp>
-
template<typename T, typename Cont = std::vector<T>>
auto auto_recv_v()¶
(1) -
template<typename T, typename Cont = std::vector<T>>
auto auto_recv_v(type_pool &pool)¶
(2) -
template<typename T, typename Cont = std::vector<T>, typename Env>
requires has_pool<std::remove_cvref_t<Env>>
auto auto_recv_v(Env &&env)¶
(3) (1) Convenience factory for a fully-managed variadic receive buffer.
Returns an owned Cont wrapped in views::auto_recv_v, which provides automatic per-rank count exchange, displacement computation, and buffer resizing.
v2::allgatherv(send_data, v2::auto_recv_v<int>(), comm); v2::alltoallv(sbuf, v2::auto_recv_v<float>(), comm);
The default container is std::vector<T>. Substitute a different container type as the second argument when needed.
(2) Convenience factory for a fully-managed variadic receive buffer with automatic type registration.
Like the zero-argument overload but additionally attaches the MPI datatype for
Tby callingpool.register_type<T>(), making it suitable for non-builtin types.v2::allgatherv(send_data, v2::auto_recv_v<MyStruct>(pool), comm);
(3) Convenience factory accepting a
comm_view_with_poolinstead of a bare pool.Equivalent to
auto_recv_v<T>(env.pool()).v2::alltoallv(sbuf, v2::auto_recv_v<MyStruct>(comm), comm);
- Template parameters:
T– Element type satisfyinghas_static_type_v.Cont– Container type (must supportresize(n)anddata()).
- Parameters:
pool– Type pool used to commit and cache the MPI datatype forT.env– Pooled communicator view; the pool is used to commit and cache the MPI datatype forT.
Defined in header
<kamping/v2/views/auto_recv_v.hpp>
-
template<typename T, typename Cont = std::vector<T>>
auto auto_recv()¶
(1) -
template<typename T, typename Cont = std::vector<T>>
auto auto_recv(type_pool &pool)¶
(2) -
template<typename T, typename Cont = std::vector<T>, typename Env>
requires has_pool<std::remove_cvref_t<Env>>
auto auto_recv(Env &&env)¶
(3) (1) Convenience factory for a fully-managed non-variadic receive buffer.
Returns an owned
Contwrapped inviews::resize, which defers the actual resize until the collective has inferred the receive count viainfer().v2::recv(v2::auto_recv<int>(), 0, comm);
The default container is
std::vector<T>. Pass a different container type as the second template argument when needed.(2) Convenience factory for a fully-managed non-variadic receive buffer with automatic type registration.
Like the zero-argument overload but additionally attaches the MPI datatype for
Tby callingpool.register_type<T>(), making it suitable for non-builtin types.v2::recv(v2::auto_recv<MyStruct>(pool), 0, comm);
(3) Convenience factory accepting a
comm_view_with_poolinstead of a bare pool.Equivalent to
auto_recv<T>(env.pool()).v2::recv(v2::auto_recv<MyStruct>(comm), 0, comm);
- Template parameters:
T– Element type.Cont– Container type (must supportresize(n)anddata()).
- Parameters:
pool– Type pool used to commit and cache the MPI datatype forT.env– Pooled communicator view; the pool is used to commit and cache the MPI datatype forT.
Defined in header
<kamping/v2/views/auto_recv.hpp>
Datatypes from a type pool¶
See Derived datatypes.
-
auto with_pool(type_pool const &pool)¶
-
template<typename Buf>
auto with_pool(Buf &&buf, type_pool const &pool)¶ -
template<has_pool Env>
auto with_pool(Env &&env)¶ -
template<typename Buf, has_pool Env>
auto with_pool(Buf &&buf, Env &&env)¶ Attaches the MPI datatype of the buffer’s element type from a
type_pool:buf | views::with_pool(pool).The element type is the range’s value type, or the
value_typemember of a buffer that is not a range (e.g. a Kokkos view). It must have been registered withpool.register_type<T>()before; an assertion fires otherwise. Usewith_auto_poolto register it on first use instead. Instead of a pool, a communicator that carries one (comm_view_with_pool) can be passed.pool.register_type<MyStruct>(); kamping::v2::bcast(v | kamping::v2::views::with_pool(pool), 0, comm); kamping::v2::send(kokkos_buf | kamping::v2::views::with_pool(pool), 1, comm);
Defined in header
<kamping/v2/type_pool.hpp>
-
auto with_auto_pool(type_pool &pool)¶
-
template<typename Buf>
auto with_auto_pool(Buf &&buf, type_pool &pool)¶ -
template<has_pool Env>
auto with_auto_pool(Env &&env)¶ -
template<typename Buf, has_pool Env>
auto with_auto_pool(Buf &&buf, Env &&env)¶ Attaches the MPI datatype of the buffer’s element type from a
type_pool, registering it on first use:buf | views::with_auto_pool(pool).Like
with_pool, but the type need not be registered in advance: the pool commits its datatype the first time it is needed. This requires akamping::types::mpi_type_traits<T>specialization describing the type.kamping::v2::bcast(v | kamping::v2::views::with_auto_pool(pool), 0, comm); kamping::v2::send(kokkos_buf | kamping::v2::views::with_auto_pool(pool), 1, comm);
Defined in header
<kamping/v2/type_pool.hpp>
-
auto with_value_pool(type_pool const &pool)¶
-
template<typename Buf>
auto with_value_pool(Buf &&buf, type_pool const &pool)¶ -
template<has_pool Env>
auto with_value_pool(Env &&env)¶ -
template<typename Buf, has_pool Env>
auto with_value_pool(Buf &&buf, Env &&env)¶ Attaches the MPI datatype of the payload of a structured buffer from a
type_pool:per_rank | views::with_value_pool(pool).Structured send buffers, such as a range of per-rank ranges or of
(value, rank)pairs, are consumed byviews::flatten_vand the dstl algorithms; their payload is the type of the values sent, not the range’s own element type. The payload type must have been registered withpool.register_type<T>()orpool.register_type<T>(dt)before; usewith_auto_value_poolto register it on first use instead.pool.register_type<MyStruct>(); kamping::v2::alltoallv(per_rank | views::with_value_pool(pool) | views::flatten_v(), rbuf, comm);
Defined in header
<kamping/v2/type_pool.hpp>
-
auto with_auto_value_pool(type_pool &pool)¶
-
template<typename Buf>
auto with_auto_value_pool(Buf &&buf, type_pool &pool)¶ -
template<has_pool Env>
auto with_auto_value_pool(Env &&env)¶ -
template<typename Buf, has_pool Env>
auto with_auto_value_pool(Buf &&buf, Env &&env)¶ Attaches the MPI datatype of the payload of a structured buffer from a
type_pool, registering it on first use:per_rank | views::with_auto_value_pool(pool).Like
with_value_pool, but the payload type need not be registered in advance. This requires akamping::types::mpi_type_traits<T>specialization describing the type.kamping::v2::alltoallv(per_rank | views::with_auto_value_pool(pool) | views::flatten_v(), rbuf, comm);
Defined in header
<kamping/v2/type_pool.hpp>
Building and splitting variable-size buffers¶
-
template<template<typename...> typename FlatTemplate = std::vector, typename CountsContainer = std::vector<int>, typename DisplsContainer = std::vector<int>>
auto flatten_v()¶
(1) -
template<typename CountsContainer = std::vector<int>, typename DisplsContainer = std::vector<int>, typename Fb>
requires (!std::same_as<std::remove_cvref_t<Fb>, resize_t>)
auto flatten_v(Fb &&flat_buf)¶
(2) -
template<typename DisplsContainer = std::vector<int>, typename Fb, typename Ct>
requires (!std::same_as<std::remove_cvref_t<Fb>, resize_t>)
auto flatten_v(Fb &&flat_buf, Ct &&counts)¶
(3) -
template<typename Fb, typename Ct, typename Dt>
requires (!std::same_as<std::remove_cvref_t<Fb>, resize_t>)
auto flatten_v(Fb &&flat_buf, Ct &&counts, Dt &&displs)¶
(4) -
template<typename CountsContainer = std::vector<int>, typename DisplsContainer = std::vector<int>, typename Fb>
auto flatten_v(resize_t, Fb &&flat_buf)¶
(5) -
template<typename DisplsContainer = std::vector<int>, typename Fb, typename Ct>
auto flatten_v(resize_t, Fb &&flat_buf, Ct &&counts)¶
(6) -
template<typename Fb, typename Ct, typename Dt>
auto flatten_v(resize_t, Fb &&flat_buf, Ct &&counts, Dt &&displs)¶
(7) (1) Flattens a structured send buffer into a variable-size send buffer:
per_rank | views::flatten_v().A structured send buffer is a range of per-rank ranges (entry
iis sent to ranki), a range of(rank, message)pairs, or a range of(value, rank)pairs. The result holds all elements contiguously, ordered by destination rank, with the matching counts and displacements, e.g. foralltoallv:std::vector<std::vector<int>> per_rank = ...; // per_rank[i] is sent to rank i auto [_, recv] = kamping::v2::alltoallv(per_rank | views::flatten_v(), kamping::v2::auto_recv_v<int>(), comm);
The flat buffer, counts and displacements are allocated internally. The template arguments select their container types, e.g.
flatten_v<std::deque>()for the flat buffer orflatten_v<std::vector, std::deque<int>>()for the counts. The overloads below flatten into storage you provide instead.(2) Flattens into the caller-provided
flat_buf, which must already be large enough; counts and displacements are allocated internally.(3) Flattens into the caller-provided
flat_bufandcounts, which must already be large enough; displacements are allocated internally.(4) Flattens into the caller-provided
flat_buf,countsanddispls, which must already be large enough.(5) Flattens into the caller-provided
flat_buf, resizing it as needed; counts and displacements are allocated internally.(6) Flattens into the caller-provided
flat_bufandcounts, resizing them as needed; displacements are allocated internally.(7) Flattens into the caller-provided
flat_buf,countsanddispls, resizing them as needed.Defined in header
<kamping/v2/views/flatten_v_view.hpp>
-
template<typename Buf>
auto chunked(Buf &&buf)¶ Splits a variadic buffer into its per-rank chunks:
buf | views::chunkedis a range ofstd::spans, chunkiholding the elements for ranki. The inverse ofviews::flatten_v.Defined in header
<kamping/v2/views/chunked_view.hpp>
Single values¶
-
template<typename T>
auto ref_single(T &val) noexcept¶ Makes a single value a buffer of one element, referring to it:
views::ref_single(value).int sum = local; kamping::v2::allreduce(kamping::v2::inplace, views::ref_single(sum), comm); // received into sum kamping::v2::send(views::ref_single(std::as_const(sum)), 0, comm); // send-only buffer
Defined in header
<kamping/v2/views/ref_single_view.hpp>