Collective operations¶
Collectives follow the same conventions as point-to-point operations: the communicator comes last, the root
defaults to rank 0 and the reduction operation to std::plus<>. Rooted collectives also have a shorthand for
non-root ranks that leaves out the buffer only the root uses, e.g. gather(sbuf, comm) on a non-root rank. See
Calling conventions.
Variable-size collectives (gatherv, scatterv, allgatherv, alltoallv) take buffers with per-rank counts and
displacements. If a receive buffer defers its counts (views::auto_counts, auto_recv_v<T>()), they are exchanged
before the operation; see Receive buffers that size themselves.
Operations with a send and a receive buffer return a kamping::v2::result, which can be unpacked with a
structured binding: auto [sbuf, rbuf] = v2::allgather(...).
Synchronization¶
-
template<convertible_to_mpi_handle<MPI_Comm> Comm>
void barrier(Comm const &comm)¶ Blocks until all ranks of
commhave called it (MPI_Barrier).Defined in header
<kamping/v2/collectives/barrier.hpp>
-
template<convertible_to_mpi_handle<MPI_Comm> Comm, convertible_to_mpi_handle_ptr<MPI_Request> Request>
void ibarrier(Comm const &comm, Request &&request)¶ Starts a non-blocking barrier on
comm(MPI_Ibarrier).The operation completes once all ranks of
commhave started the barrier.- Parameters:
request– Receives the request of the barrier; the caller must complete it.
Defined in header
<kamping/v2/collectives/ibarrier.hpp>
Broadcast¶
-
template<send_recv_buffer SRBuf, rank Root, convertible_to_mpi_handle<MPI_Comm> Comm>
SRBuf bcast(SRBuf &&send_recv_buf, Root root, Comm const &comm)¶
(1) -
template<send_recv_buffer SRBuf, convertible_to_mpi_handle<MPI_Comm> Comm>
SRBuf bcast(SRBuf &&send_recv_buf, Comm const &comm)¶
(2) (1) Broadcasts
send_recv_buffromrootto all ranks (MPI_Bcast).If the buffer is a deferred receive buffer (e.g.
views::resize), root’s count is broadcast first and the buffer is resized on the other ranks.(2) Broadcasts
send_recv_buffrom rank 0 to all ranks; see the overload above.- Returns:
The buffer (owned if passed as rvalue, borrowed otherwise).
Defined in header
<kamping/v2/collectives/bcast.hpp>
Gather and scatter¶
-
template<send_buffer SBuf, recv_buffer RBuf, rank Root, convertible_to_mpi_handle<MPI_Comm> Comm>
result<SBuf, RBuf> gather(SBuf &&sbuf, RBuf &&rbuf, Root root, Comm const &comm)¶
(1) -
template<send_buffer SBuf, recv_buffer RBuf, convertible_to_mpi_handle<MPI_Comm> Comm>
result<SBuf, RBuf> gather(SBuf &&sbuf, RBuf &&rbuf, Comm const &comm)¶
(2) -
template<send_buffer SBuf, rank Root, convertible_to_mpi_handle<MPI_Comm> Comm>
SBuf gather(SBuf &&sbuf, Root root, Comm const &comm)¶
(3) -
template<send_buffer SBuf, convertible_to_mpi_handle<MPI_Comm> Comm>
SBuf gather(SBuf &&sbuf, Comm const &comm)¶
(4) (1) Gathers
sbuffrom all ranks intorbufonroot(MPI_Gather).On root,
rbufmay be a deferred receive buffer (e.g.views::resize); on the other ranks it is ignored, so passnull_bufor use the overloads without receive buffer.(2) Gathers
sbuffrom all ranks intorbufon rank 0; see the overload above.(3) Non-root shorthand of
gather: contributessbufto the gather onroot, without a receive buffer.(4) Non-root shorthand of
gather: contributessbufto the gather on rank 0, without a receive buffer.- Returns:
(1) The send and receive buffer (owned if passed as rvalue, borrowed otherwise).
(3, 4) The send buffer.
Defined in header
<kamping/v2/collectives/gather.hpp>
-
template<send_buffer SBuf, recv_buffer_v RBuf, rank Root, convertible_to_mpi_handle<MPI_Comm> Comm>
result<SBuf, RBuf> gatherv(SBuf &&sbuf, RBuf &&rbuf, Root root, Comm const &comm)¶
(1) -
template<send_buffer SBuf, recv_buffer_v RBuf, convertible_to_mpi_handle<MPI_Comm> Comm>
result<SBuf, RBuf> gatherv(SBuf &&sbuf, RBuf &&rbuf, Comm const &comm)¶
(2) (1) Gathers variable amounts of data from all ranks into the variadic buffer
rbufonroot(MPI_Gatherv).On root,
rbufmay have deferred counts (e.g.auto_recv_v<T>()); the counts are then gathered first. The other ranks must then passauto_null_recv_v()to take part in that exchange, ornull_buf_vif root’s counts are given explicitly. There is no non-root shorthand, because which of the two is right depends on root.(2) Gathers into
rbufon rank 0; see the overload above.- Returns:
The send and receive buffer (owned if passed as rvalue, borrowed otherwise).
Defined in header
<kamping/v2/collectives/gatherv.hpp>
-
template<send_buffer SBuf, recv_buffer RBuf, rank Root, convertible_to_mpi_handle<MPI_Comm> Comm>
result<SBuf, RBuf> scatter(SBuf &&sbuf, RBuf &&rbuf, Root root, Comm const &comm)¶
(1) -
template<send_buffer SBuf, recv_buffer RBuf, convertible_to_mpi_handle<MPI_Comm> Comm>
result<SBuf, RBuf> scatter(SBuf &&sbuf, RBuf &&rbuf, Comm const &comm)¶
(2) -
template<recv_buffer RBuf, rank Root, convertible_to_mpi_handle<MPI_Comm> Comm>
RBuf scatter(RBuf &&rbuf, Root root, Comm const &comm)¶
(3) -
template<recv_buffer RBuf, convertible_to_mpi_handle<MPI_Comm> Comm>
RBuf scatter(RBuf &&rbuf, Comm const &comm)¶
(4) (1) Distributes equal shares of
sbufonrootto all ranks, receiving intorbuf(MPI_Scatter).On root, the count of
sbufmust be divisible by the communicator size, andrbufmay beinplaceto keep root’s share insbuf. The other ranks passnull_bufassbufor use the overloads without send buffer.rbufmay be a deferred receive buffer (e.g.views::resize).(2) Scatters from rank 0; see the overload above.
(3) Non-root shorthand of
scatter: receives this rank’s share fromrootintorbuf, without a send buffer.(4) Non-root shorthand of
scatter: receives this rank’s share from rank 0 intorbuf, without a send buffer.- Returns:
(1) The send and receive buffer (owned if passed as rvalue, borrowed otherwise).
(3, 4) The receive buffer.
Defined in header
<kamping/v2/collectives/scatter.hpp>
-
template<send_buffer_v SBuf, recv_buffer RBuf, rank Root, convertible_to_mpi_handle<MPI_Comm> Comm>
result<SBuf, RBuf> scatterv(SBuf &&sbuf, RBuf &&rbuf, Root root, Comm const &comm)¶
(1) -
template<send_buffer_v SBuf, recv_buffer RBuf, convertible_to_mpi_handle<MPI_Comm> Comm>
result<SBuf, RBuf> scatterv(SBuf &&sbuf, RBuf &&rbuf, Comm const &comm)¶
(2) -
template<recv_buffer RBuf, rank Root, convertible_to_mpi_handle<MPI_Comm> Comm>
RBuf scatterv(RBuf &&rbuf, Root root, Comm const &comm)¶
(3) -
template<recv_buffer RBuf, convertible_to_mpi_handle<MPI_Comm> Comm>
RBuf scatterv(RBuf &&rbuf, Comm const &comm)¶
(4) (1) Distributes parts of the variadic buffer
sbufonrootto all ranks, receiving intorbuf(MPI_Scatterv).The other ranks pass
null_buf_vassbufor use the overloads without send buffer.rbufmay be a deferred receive buffer (e.g.views::resize); root’s counts are then scattered first.(2) Scatters from rank 0; see the overload above.
(3) Non-root shorthand of
scatterv: receives this rank’s part fromrootintorbuf, without a send buffer.(4) Non-root shorthand of
scatterv: receives this rank’s part from rank 0 intorbuf, without a send buffer.- Returns:
(1) The send and receive buffer (owned if passed as rvalue, borrowed otherwise).
(3, 4) The receive buffer.
Defined in header
<kamping/v2/collectives/scatterv.hpp>
-
template<send_buffer SBuf, recv_buffer RBuf, convertible_to_mpi_handle<MPI_Comm> Comm>
result<SBuf, RBuf> allgather(SBuf &&sbuf, RBuf &&rbuf, Comm const &comm)¶ Gathers
sbuffrom all ranks intorbufon every rank (MPI_Allgather).rbufmay be a deferred receive buffer (e.g.views::resize), which is resized tocomm_size * count(sbuf).- Returns:
The send and receive buffer (owned if passed as rvalue, borrowed otherwise).
Defined in header
<kamping/v2/collectives/allgather.hpp>
-
template<send_buffer SBuf, recv_buffer_v RBuf, convertible_to_mpi_handle<MPI_Comm> Comm>
result<SBuf, RBuf> allgatherv(SBuf &&sbuf, RBuf &&rbuf, Comm const &comm)¶ Gathers a variable amount of data from all ranks into the variadic buffer
rbufon every rank (MPI_Allgatherv).If
rbufhas deferred counts (e.g.auto_recv_v<T>()), the counts are exchanged first andrbufis sized to fit.- Returns:
The send and receive buffer (owned if passed as rvalue, borrowed otherwise).
Defined in header
<kamping/v2/collectives/allgatherv.hpp>
All-to-all¶
-
template<send_buffer SBuf, recv_buffer RBuf, convertible_to_mpi_handle<MPI_Comm> Comm>
result<SBuf, RBuf> alltoall(SBuf &&sbuf, RBuf &&rbuf, Comm const &comm)¶ Sends an equal share of
sbufto every rank and receives one share from every rank intorbuf(MPI_Alltoall).rbufmay be a deferred receive buffer (e.g.views::resize), which is resized tocount(sbuf).- Returns:
The send and receive buffer (owned if passed as rvalue, borrowed otherwise).
Defined in header
<kamping/v2/collectives/alltoall.hpp>
-
template<send_buffer_v SBuf, recv_buffer_v RBuf, convertible_to_mpi_handle<MPI_Comm> Comm>
result<SBuf, RBuf> alltoallv(SBuf &&sbuf, RBuf &&rbuf, Comm const &comm)¶ Exchanges variable amounts of data between all ranks (
MPI_Alltoallv).sbufis a variadic buffer, e.g.data | views::with_counts(c) | views::auto_displs()ornested | views::flatten_v(). Ifrbufhas deferred counts (e.g.auto_recv_v<T>()), the counts are exchanged first andrbufis sized to fit.- Returns:
The send and receive buffer (owned if passed as rvalue, borrowed otherwise).
Defined in header
<kamping/v2/collectives/alltoallv.hpp>
Reductions¶
-
template<send_buffer SBuf, recv_buffer RBuf, valid_op<SBuf, RBuf> Op, rank Root, convertible_to_mpi_handle<MPI_Comm> Comm>
result<SBuf, RBuf> reduce(SBuf &&sbuf, RBuf &&rbuf, Op const &op, Root root, Comm const &comm)¶
(1) -
template<send_buffer SBuf, recv_buffer RBuf, valid_op<SBuf, RBuf> Op, convertible_to_mpi_handle<MPI_Comm> Comm>
result<SBuf, RBuf> reduce(SBuf &&sbuf, RBuf &&rbuf, Op const &op, Comm const &comm)¶
(2) -
template<send_buffer SBuf, recv_buffer RBuf, convertible_to_mpi_handle<MPI_Comm> Comm>
requires valid_op<std::plus<>, SBuf, RBuf>
result<SBuf, RBuf> reduce(SBuf &&sbuf, RBuf &&rbuf, Comm const &comm)¶
(3) -
template<send_buffer SBuf, valid_op<SBuf, null_buf_t> Op, rank Root, convertible_to_mpi_handle<MPI_Comm> Comm>
SBuf reduce(SBuf &&sbuf, Op const &op, Root root, Comm const &comm)¶
(4) -
template<send_buffer SBuf, valid_op<SBuf, null_buf_t> Op, convertible_to_mpi_handle<MPI_Comm> Comm>
SBuf reduce(SBuf &&sbuf, Op const &op, Comm const &comm)¶
(5) -
template<send_buffer SBuf, convertible_to_mpi_handle<MPI_Comm> Comm>
requires valid_op<std::plus<>, SBuf, null_buf_t>
SBuf reduce(SBuf &&sbuf, Comm const &comm)¶
(6) (1) Reduces
sbufacross all ranks withopand stores the result inrbufonroot(MPI_Reduce).Pass
inplaceassbufon root to reducerbufin place. On root,rbufmay be a deferred receive buffer (e.g.views::resize); on the other ranks it is ignored, so passnull_bufor use the overloads without receive buffer.(2) Reduces with
opto rank 0; see the overload above.(3) Sums to rank 0; see the overload above.
(4) Non-root shorthand of
reduce: contributessbufto the reduction withoponroot, without a receive buffer.(5) Non-root shorthand of
reduce: contributessbufto the reduction withopon rank 0.(6) Non-root shorthand of
reduce: contributessbufto the sum on rank 0.- Parameters:
op– Reduction operation: anMPI_Op, a standard functor such asstd::plus<>, or the result ofmake_op.
- Returns:
(1) The send and receive buffer (owned if passed as rvalue, borrowed otherwise).
(4-6) The send buffer.
Defined in header
<kamping/v2/collectives/reduce.hpp>
-
template<send_buffer SBuf, recv_buffer RBuf, valid_op<SBuf, RBuf> Op, convertible_to_mpi_handle<MPI_Comm> Comm>
result<SBuf, RBuf> allreduce(SBuf &&sbuf, RBuf &&rbuf, Op const &op, Comm const &comm)¶
(1) -
template<send_buffer SBuf, recv_buffer RBuf, convertible_to_mpi_handle<MPI_Comm> Comm>
requires valid_op<std::plus<>, SBuf, RBuf>
result<SBuf, RBuf> allreduce(SBuf &&sbuf, RBuf &&rbuf, Comm const &comm)¶
(2) (1) Reduces
sbufacross all ranks withopand stores the result inrbufon every rank (MPI_Allreduce).Pass
inplaceassbufto userbuffor both input and output.rbufmay be a deferred receive buffer (e.g.views::resize).(2) Like the overload above, with
std::plus<>as operation.- Parameters:
op– Reduction operation: anMPI_Op, a standard functor such asstd::plus<>, or the result ofmake_op.
- Returns:
The send and receive buffer (owned if passed as rvalue, borrowed otherwise).
Defined in header
<kamping/v2/collectives/allreduce.hpp>
-
template<send_buffer SBuf, recv_buffer RBuf, valid_op<SBuf, RBuf> Op, convertible_to_mpi_handle<MPI_Comm> Comm>
result<SBuf, RBuf> scan(SBuf &&sbuf, RBuf &&rbuf, Op const &op, Comm const &comm)¶
(1) -
template<send_buffer SBuf, recv_buffer RBuf, convertible_to_mpi_handle<MPI_Comm> Comm>
requires valid_op<std::plus<>, SBuf, RBuf>
result<SBuf, RBuf> scan(SBuf &&sbuf, RBuf &&rbuf, Comm const &comm)¶
(2) (1) Computes the inclusive prefix reduction of
sbufover the ranks withopintorbuf(MPI_Scan).Pass
inplaceassbufto userbuffor both input and output.rbufmay be a deferred receive buffer (e.g.views::resize).(2) Like the overload above, with
std::plus<>as operation.- Parameters:
op– Reduction operation: anMPI_Op, a standard functor such asstd::plus<>, or the result ofmake_op.
- Returns:
The send and receive buffer (owned if passed as rvalue, borrowed otherwise).
Defined in header
<kamping/v2/collectives/scan.hpp>
-
template<send_buffer SBuf, recv_buffer RBuf, valid_op<SBuf, RBuf> Op, convertible_to_mpi_handle<MPI_Comm> Comm>
result<SBuf, RBuf> exscan(SBuf &&sbuf, RBuf &&rbuf, Op const &op, Comm const &comm)¶
(1) -
template<send_buffer SBuf, recv_buffer RBuf, convertible_to_mpi_handle<MPI_Comm> Comm>
requires valid_op<std::plus<>, SBuf, RBuf>
result<SBuf, RBuf> exscan(SBuf &&sbuf, RBuf &&rbuf, Comm const &comm)¶
(2) (1) Computes the exclusive prefix reduction of
sbufover the ranks withopintorbuf(MPI_Exscan).Pass
inplaceassbufto userbuffor both input and output.rbufmay be a deferred receive buffer (e.g.views::resize).The content of
rbufon rank 0 is undefined after the call, as in MPI.(2) Like the overload above, with
std::plus<>as operation.- Parameters:
op– Reduction operation: anMPI_Op, a standard functor such asstd::plus<>, or the result ofmake_op.
- Returns:
The send and receive buffer (owned if passed as rvalue, borrowed otherwise).
Defined in header
<kamping/v2/collectives/exscan.hpp>
Reduction operations¶
An operation is an MPI_Op, a standard function object such as std::plus<> or std::multiplies<> (mapped to
the builtin operation where one exists), or any callable wrapped with make_op.
-
template<typename Op, typename SBuf, typename RBuf>
concept valid_op¶ template<typename Op, typename SBuf, typename RBuf> concept valid_op = requires(Op const& op, SBuf const& sbuf, RBuf const& rbuf) { mpi::experimental::as_mpi_op(op, sbuf, rbuf); }
Opcan be used as reduction operation on buffers of typesSBufandRBuf, i.e.as_mpi_opis defined.Defined in header
<kamping/v2/ops.hpp>
-
template<commutativity_tag Commutativity = non_commutative_tag>
auto make_op(detail::op_callback_t callback, Commutativity = {})¶
(1) -
template<typename T, typename Op, commutativity_tag Commutativity = non_commutative_tag>
requires std::is_default_constructible_v<std::remove_cvref_t<Op>> && std::is_invocable_r_v<T, std::remove_cvref_t<Op>, T const&, T const&>
auto make_op(Op &&op, Commutativity = {})¶
(2) (1) Creates an
MPI_Opfrom a raw MPI reduction callback.Use this when you already have a function with MPI’s callback signature
void(void* invec, void* inoutvec, int* len, MPI_Datatype* datatype). No element type is required because the callback is already type-erased.(2) Creates an
MPI_Opfrom a default-constructible binary functor.Handles stateless functors and captureless lambdas (which are default-constructible in C++20). The element-wise application is provided by
kamping::types::ScopedFunctorOp; the functor must be callable asT(T const&, T const&).Stateful (capturing) lambdas are intentionally not supported here — they are neither default-constructible nor convertible to a raw callback. Wrap the required state in a default-constructible functor, or create the callback yourself and pass it to the overload above.
- Template parameters:
Commutativity– Commutativity tag type; defaults to non-commutative.T– The element type the operation is applied to. Must be specified explicitly, e.g.make_op<int>(...).Op– Functor type (deduced).
- Parameters:
callback– Non-null MPI callback function pointer.op– The binary operation.
- Returns:
(1) A
kamping::types::ScopedCallbackOpowning the freshly createdMPI_Op.(2) A
kamping::types::ScopedFunctorOpowning the freshly createdMPI_Op.
Defined in header
<kamping/v2/ops.hpp>
-
commutative_tag commutative¶
Tag value marking an operation as commutative (re-exported from
kamping::ops).Defined in header
<kamping/v2/ops.hpp>
-
non_commutative_tag non_commutative¶
Tag value marking an operation as non-commutative (re-exported from
kamping::ops).Defined in header
<kamping/v2/ops.hpp>
Special buffers¶
-
inplace_t inplace¶
MPI_IN_PLACE: passed as the send buffer of a collective, the receive buffer holds the input and receives the result.The receive buffer must already have the right size; it cannot be resized for an in-place operation.
int sum = local; v2::allreduce(v2::inplace, views::ref_single(sum), comm);
Defined in header
<kamping/v2/sentinels.hpp>
-
null_buf_t null_buf¶
An empty buffer: for the buffer of a rooted collective that only the root uses, or as an empty message.
The non-root shorthands of
gather,scatterandreducepass it for you.v2::gather(local_data, v2::null_buf, root, comm); // on a non-root rank v2::send(v2::null_buf, dest, tag, comm); // a message without data
Defined in header
<kamping/v2/sentinels.hpp>
-
null_buf_v_t null_buf_v¶
An empty variable-size buffer, for the buffer of
gathervorscattervthat only the root uses, if the root provides its counts. If the root’s receive buffer obtains its counts from the others (e.g.auto_recv_v), non-root ranks passauto_null_recv_v()instead.v2::gatherv(local_data, v2::null_buf_v, root, comm); // on a non-root rank
Defined in header
<kamping/v2/sentinels.hpp>
-
auto_null_recv_v_t auto_null_recv_v() noexcept¶
An empty receive buffer for
gathervon non-root ranks, if the root’s receive buffer obtains its counts from the others, e.g.auto_recv_v: the non-root ranks then still take part in the count exchange.if (comm.rank() == root) { auto [_, all] = v2::gatherv(local_data, v2::auto_recv_v<int>(), root, comm); } else { v2::gatherv(local_data, v2::auto_null_recv_v(), root, comm); }
Pass the result directly, as here; it cannot be used through a
constvariable.Defined in header
<kamping/v2/sentinels.hpp>
-
bottom_t bottom¶
A buffer at
MPI_BOTTOM, for derived datatypes that contain absolute addresses.Not a complete buffer on its own: add the datatype and the count with views.
v2::send(v2::bottom | views::with_type(absolute_type) | views::with_count(1), dest, comm);
Defined in header
<kamping/v2/sentinels.hpp>