KaMPIng 0.1.1
Flexible and (near) zero-overhead C++ bindings for MPI
Loading...
Searching...
No Matches
alltoall_dispatch.hpp
Go to the documentation of this file.
1// This file is part of KaMPIng.
2//
3// Copyright 2024 The KaMPIng Authors
4//
5// KaMPIng is free software : you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
7// version. KaMPIng is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
9// for more details.
10//
11// You should have received a copy of the GNU Lesser General Public License along with KaMPIng. If not, see
12// <https://www.gnu.org/licenses/>.
13
14/// @file
15/// @brief Plugin to dispatch to one of multiple possible algorithms for alltoallv exchanges.
16
18#include "kamping/collectives/allreduce.hpp"
19#include "kamping/collectives/alltoall.hpp"
20#include "kamping/communicator.hpp"
25#include "kamping/plugin/plugin_helpers.hpp"
26
27#pragma once
28
29namespace kamping::plugin {
30
31namespace dispatch_alltoall {
32
33/// @brief Parameter types used for the DispatchAlltoall plugin.
34enum class ParameterType {
35 comm_volume_threshold ///< Tag used to the communication volume threshold to use within alltoall_dispatch.
36};
37
38/// @brief The threshold for the maximum bottleneck communication volume in number of bytes indicating for when to
39/// switch from grid to builtin alltoall.
40/// @param num_bytes Threshold volume in number of bytes.
41/// @return The corresponding parameter object.
42inline auto comm_volume_threshold(size_t num_bytes) {
45 ParameterType::comm_volume_threshold,
46 internal::BufferModifiability::constant,
47 internal::BufferType::in_buffer,
49 size_t>(std::move(num_bytes));
50}
51
52//
53namespace internal {
54/// @brief Predicate to check whether an argument provided to alltoallv_dispatch shall be discarded in the internal
55/// calls.
57 /// @brief Function to check whether an argument provided to \ref DispatchAlltoall::alltoallv_dispatch() shall be
58 /// discarded in the send call.
59 ///
60 /// @tparam Arg Argument to be checked.
61 /// @return \c True (i.e. discard) iff Arg's parameter_type is `volume_threshold`, `send_counts`.
62 template <typename Arg>
63 static constexpr bool discard() {
65 std::integral_constant<
67 dispatch_alltoall::ParameterType::comm_volume_threshold>,
68 std::integral_constant<kamping::internal::ParameterType, kamping::internal::ParameterType::send_counts>>;
69 using ptype_entry =
70 std::integral_constant<kamping::internal::parameter_type_t<Arg>, kamping::internal::parameter_type_v<Arg>>;
71 return ptypes_to_ignore::contains<ptype_entry>;
72 }
73};
74
75} // namespace internal
76
77} // namespace dispatch_alltoall
78/// @brief Plugin providing an alltoallv exchange method which calls one of multiple underlying alltoallv exchange
79/// algorithms depending on the communication volume.
80/// @see \ref DispatchAlltoall::alltoallv_dispatch() for more information.
81template <typename Comm, template <typename...> typename DefaultContainerType>
82class DispatchAlltoall : public plugin::PluginBase<Comm, DefaultContainerType, DispatchAlltoall> {
83public:
84 /// @brief Alltoallv exchange method which uses the communication volume to either exchange the data using
85 /// GridCommunicator::alltoallv() (latency in about sqrt(comm.size())) or builtin MPI_Alltoallv (potentially linear
86 /// latency).
87 ///
88 /// If the bottleneck send communication volume on all ranks is smaller than a given threshold (in number bytes),
89 /// our grid alltoall communication is used. Otherwise we use the builtin MPI alltoallv exchange.
90 ///
91 /// The following parameters are required:
92 /// - \ref kamping::send_buf() containing the data that is sent to each rank. The size of this buffer has to be at
93 /// least the sum of the send_counts argument.
94 ///
95 /// - \ref kamping::send_counts() containing the number of elements to send to each rank.
96 ///
97 /// The following buffers are optional:
98 /// - \ref dispatch_alltoall::comm_volume_threshold() containing the threshold for the maximum bottleneck
99 /// communication volume in bytes indicating to switch from grid to builtin alltoall exchange. If ommitted, a
100 /// threshold value of 2000 bytes is used.
101 /// - \ref kamping::recv_counts() containing the number of elements to receive from each rank.
102 /// This parameter is mandatory if \ref kamping::recv_type() is given.
103 ///
104 /// - \ref kamping::recv_buf() containing a buffer for the output. Afterwards, this buffer will contain
105 /// the data received as specified for send_buf. The buffer will be resized according to the buffer's
106 /// kamping::BufferResizePolicy. If resize policy is kamping::BufferResizePolicy::no_resize, the buffer's underlying
107 /// storage must be large enough to store all received elements.
108 ///
109 /// @tparam Args Automatically deducted template parameters.
110 /// @param args All required and any number of the optional parameters described above.
111 template <typename... Args>
112 auto alltoallv_dispatch(Args... args) const {
113 [[maybe_unused]] auto& self = this->to_communicator();
114 auto& send_buf = internal::select_parameter_type<internal::ParameterType::send_buf>(args...);
115 using send_value_type = typename std::remove_reference_t<decltype(send_buf)>::value_type;
116
117 // get send counts (needed for algorithm dispatch)
118 auto const& send_counts = internal::select_parameter_type<internal::ParameterType::send_counts>(args...)
120
121 // get send communication volume threshold for when to switch from grid to builtin alltoall
122 using volume_threshold_param_type = std::integral_constant<
124 dispatch_alltoall::ParameterType::comm_volume_threshold>;
125 constexpr size_t volume_threshold_default_value = 2000;
127 decltype(dispatch_alltoall::comm_volume_threshold(volume_threshold_default_value));
128 auto&& volume_threshold =
129 internal::select_parameter_type_or_default<volume_threshold_param_type, default_comm_volume_threshold_type>(
131 args...
132 );
133
134 size_t const max_bottleneck_send_volume =
135 self.allreduce_single(kamping::send_buf(send_buf.size()), op(ops::max<size_t>{}));
136
137 /// remove comm_volume_threshold and unpacked send_counts from caller provided argument list before forwarding
138 /// it underlying allotall exchanges
139 auto const filter_args = [&]() {
141 };
142
143 if (max_bottleneck_send_volume * sizeof(send_value_type) < volume_threshold.get_single_element()) {
144 // max bottleneck send volume is small ==> use grid exchange
145 auto callable = [&](auto... argsargs) {
146 initialize();
147 return _grid_communicator.value().alltoallv(kamping::send_counts(send_counts), std::move(argsargs)...);
148 };
149 return std::apply(callable, filter_args());
150 }
151
152 // otherwise resort to builtin MPI_Alltoallv.
153 auto callable = [&](auto... argsargs) {
154 return self.alltoallv(kamping::send_counts(send_counts), std::move(argsargs)...);
155 };
156 return std::apply(callable, filter_args());
157 }
158
159 /// @brief Initialized the grid communicator. If not explicitly called by the user this will be done during the
160 /// first call to alltoallv_dispatch which internally uses grid communication.
161 void initialize() const {
162 if (_grid_communicator.has_value()) {
163 return;
164 } else {
165 _grid_communicator = std::make_optional(this->to_communicator().make_grid_communicator());
166 }
167 }
168
169private:
170 mutable std::optional<grid::GridCommunicator<DefaultContainerType>>
171 _grid_communicator; ///< Grid communicator to use for grid alltoall exchange.
172};
173} // namespace kamping::plugin
ParameterType
Parameter types used for the DispatchAlltoall plugin.
Definition alltoall_dispatch.hpp:34
auto comm_volume_threshold(size_t num_bytes)
The threshold for the maximum bottleneck communication volume in number of bytes indicating for when ...
Definition alltoall_dispatch.hpp:42
Plugin to enable grid communication.
File containing the SparseAlltoall plugin.
Helper functions that make casts safer.
STL-compatible allocator for requesting memory using the builtin MPI allocator.
Definition allocator.hpp:32
Plugin providing an alltoallv exchange method which calls one of multiple underlying alltoallv exchan...
Definition alltoall_dispatch.hpp:82
auto alltoallv_dispatch(Args... args) const
Alltoallv exchange method which uses the communication volume to either exchange the data using GridC...
Definition alltoall_dispatch.hpp:112
void initialize() const
Initialized the grid communicator. If not explicitly called by the user this will be done during the ...
Definition alltoall_dispatch.hpp:161
Wrapper for MPI functions that don't require a communicator.
@ no_resize
Policy indicating that the underlying buffer shall never be resized.
internal::OperationBuilder< Op, Commutative > op(Op &&op, Commutative commute=ops::internal::undefined_commutative_tag{})
Passes a reduction operation to ther underlying call. Accepts function objects, lambdas,...
Definition named_parameters.hpp:1155
auto send_buf(internal::ignore_t< Data > ignore)
Generates a dummy send buf that wraps a nullptr.
Definition named_parameters.hpp:51
auto send_counts(Container &&container)
Passes a container as send counts to the underlying call, i.e. the container's storage must contain t...
Definition named_parameters.hpp:203
auto make_data_buffer(Data &&data)
Creates a user allocated DataBuffer containing the supplied data (a container or a single element)
Definition data_buffer.hpp:798
Parameter objects return by named parameter factory functions.
Wrapper struct for std::max.
Definition mpi_ops.hpp:38
Helper type for representing a type list.
Definition parameter_objects.hpp:326
Helper class for using CRTP for mixins. Which are used to implement kamping plugins.
Definition plugin_helpers.hpp:32
Predicate to check whether an argument provided to alltoallv_dispatch shall be discarded in the inter...
Definition alltoall_dispatch.hpp:56
static constexpr bool discard()
Function to check whether an argument provided to DispatchAlltoall::alltoallv_dispatch() shall be dis...
Definition alltoall_dispatch.hpp:63