KaMPIng 0.1.1
Flexible and (near) zero-overhead C++ bindings for MPI
Loading...
Searching...
No Matches
iallreduce.hpp
1// This file is part of KaMPIng.
2//
3// Copyright 2022-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#pragma once
15
16#include <tuple>
17#include <type_traits>
18
19#include <kassert/kassert.hpp>
20#include <mpi.h>
21
22#include "kamping/assertion_levels.hpp"
24#include "kamping/collectives/collectives_helpers.hpp"
25#include "kamping/comm_helper/is_same_on_all_ranks.hpp"
26#include "kamping/communicator.hpp"
34#include "kamping/result.hpp"
35
36/// @addtogroup kamping_collectives
37/// @{
38
39/// @brief Wrapper for \c MPI_Iallreduce.
40///
41/// This wraps \c MPI_Iallreduce. The operation combines the elements in the input buffer provided via \c
42/// kamping::send_buf() and returns the combined value on all ranks.
43///
44/// The following parameters are required:
45/// - \ref kamping::send_buf() containing the data that is sent to each rank. This buffer has to have the same
46/// size at each rank.
47/// - \ref kamping::op() wrapping the operation to apply to the input. If \ref kamping::send_recv_type() is
48/// provided explicitly, the compatibility of the type and operation has to be ensured by the user.
49///
50/// The following parameters are optional:
51/// - \ref kamping::recv_buf() containing a buffer for the output.
52///
53/// - \ref kamping::send_recv_count() specifying how many elements of the send buffer take part in the
54/// reduction. If omitted, the size of send buffer is used. This parameter is mandatory if \ref
55/// kamping::send_recv_type() is given.
56///
57/// - \ref kamping::send_recv_type() specifying the \c MPI datatype to use as send type. If omitted, the \c MPI
58/// datatype is derived automatically based on send_buf's underlying \c value_type.
59///
60/// - \ref kamping::request() The request object to associate this operation with. Defaults to a library
61/// allocated request object, which can be access via the returned result.
62///
63/// @tparam Args Automatically deduced template parameters.
64/// @param args All required and any number of the optional parameters described above.
65/// @return Result object wrapping the output parameters to be returned by value.
66///
67/// @see \ref docs/parameter_handling.md for general information about parameter handling in KaMPIng.
68/// <hr>
69/// \include{doc} docs/resize_policy.dox
70template <
71 template <typename...>
72 typename DefaultContainerType,
73 template <typename, template <typename...> typename>
74 typename... Plugins>
75template <typename... Args>
77 using namespace kamping::internal;
79 Args,
82 );
83
84 // Get the send buffer and deduce the send and recv value types.
85 auto&& send_buf = select_parameter_type<ParameterType::send_buf>(args...).construct_buffer_or_rebind();
86 using send_value_type = typename std::remove_reference_t<decltype(send_buf)>::value_type;
87 using default_recv_value_type = std::remove_const_t<send_value_type>;
88
89 // Deduce the recv buffer type and get (if provided) the recv buffer or allocate one (if not provided).
91 auto&& recv_buf =
94 using recv_value_type = typename std::remove_reference_t<decltype(recv_buf)>::value_type;
95 static_assert(
96 std::is_same_v<std::remove_const_t<send_value_type>, recv_value_type>,
97 "Types of send and receive buffers do not match."
98 );
99
100 // Get the send_recv_type.
102 [[maybe_unused]] constexpr bool send_recv_type_is_in_param = !has_to_be_computed<decltype(send_recv_type)>;
103
104 // Get the operation used for the reduction. The signature of the provided function is checked while
105 // building.
106 auto operation = [&]() {
109 return make_data_buffer<
111 ParameterType::op,
112 BufferModifiability::modifiable,
113 BufferType::in_buffer,
115 }();
120 .construct_buffer_or_rebind();
121 if constexpr (has_to_be_computed<decltype(send_recv_count)>) {
122 send_recv_count.underlying() = asserting_cast<int>(send_buf.size());
123 }
124
125 using default_request_param = decltype(kamping::request());
126 auto&& request_param =
127 internal::select_parameter_type_or_default<internal::ParameterType::request, default_request_param>(
128 std::tuple{},
129 args...
130 );
131
133 return asserting_cast<size_t>(send_recv_count.get_single_element());
134 };
135 recv_buf.resize_if_requested(compute_required_recv_buf_size);
136
137 KASSERT(
138 // if the send type is user provided, kamping cannot make any assumptions about the required size of the
139 // recv buffer
141 "Recv buffer is not large enough to hold all received elements.",
143 );
144
145 // store all parameters/buffers for which we have to ensure pointer stability until completion of the immediate MPI
146 // call on the heap.
147 auto buffers_on_heap = move_buffer_to_heap(
148 std::move(send_buf),
149 std::move(recv_buf),
150 std::move(send_recv_count),
151 std::move(send_recv_type),
152 std::move(operation)
153 );
154
155 // Perform the MPI_Allreduce call and return.
157 select_parameter_type_in_tuple<ParameterType::send_buf>(*buffers_on_heap).data(), // sendbuf
158 select_parameter_type_in_tuple<ParameterType::recv_buf>(*buffers_on_heap).data(), // recvbuf,
159 select_parameter_type_in_tuple<ParameterType::send_recv_count>(*buffers_on_heap).get_single_element(), // count,
161 .get_single_element(), // datatype,
162 select_parameter_type_in_tuple<ParameterType::op>(*buffers_on_heap).underlying().op(), // op,
163 mpi_communicator(), // communicator,
164 request_param.underlying().request_ptr() // request
165 );
166 this->mpi_error_hook(err, "MPI_Iallreduce");
167
168 return internal::make_nonblocking_result<std::tuple<Args...>>(std::move(request_param), std::move(buffers_on_heap));
169}
170/// @}
Helper functions that make casts safer.
STL-compatible allocator for requesting memory using the builtin MPI allocator.
Definition allocator.hpp:32
T value_type
The value type.
Definition allocator.hpp:53
Code for error handling.
constexpr int light
Assertion level for lightweight assertions.
Definition assertion_levels.hpp:13
auto iallreduce(Args... args) const
Wrapper for MPI_Iallreduce.
Definition iallreduce.hpp:76
static constexpr auto alloc_new
Convenience wrapper for creating library allocated containers. See AllocNewT for details.
Definition data_buffer.hpp:194
@ 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 request()
Internally allocate a request object and return it to the user.
Definition named_parameters.hpp:1122
auto recv_buf(Container &&container)
Passes a container, into which the received elements will be written, to the underlying call....
Definition named_parameters.hpp:859
auto send_buf(internal::ignore_t< Data > ignore)
Generates a dummy send buf that wraps a nullptr.
Definition named_parameters.hpp:51
auto send_recv_count(int count)
Passes count as send/recv count to the underlying call.
Definition named_parameters.hpp:529
auto send_recv_type(MPI_Datatype send_recv_type)
Passes send_recv_type as send/recv type to the underlying call. (This parameter is in MPI routines su...
Definition named_parameters.hpp:1282
auto send_recv_count_out()
Indicates to deduce the send/recv count and return it to the caller as part of the underlying call's ...
Definition named_parameters.hpp:555
ParameterType
Each input parameter to one of the MPI calls wrapped by KaMPIng needs to has one of the following tag...
Definition named_parameter_types.hpp:33
decltype(auto) select_parameter_type_or_default(std::tuple< DefaultArguments... > default_arguments, Args &... args)
Checks if parameter with requested parameter type exists, if not constructs a default value.
Definition named_parameter_selection.hpp:239
Utility that maps C++ types to types that can be understood by MPI.
Template magic to check named parameters passed to wrappers at compile time.
#define KAMPING_REQUIRED_PARAMETERS(...)
Wrapper to pass (possibly empty) list of parameter type names as required parameters to KAMPING_CHECK...
Definition named_parameter_check.hpp:52
#define KAMPING_OPTIONAL_PARAMETERS(...)
Wrapper to pass (possibly empty) list of parameter type names as optional parameters to KAMPING_CHECK...
Definition named_parameter_check.hpp:58
#define KAMPING_CHECK_PARAMETERS(args, required, optional)
Assertion macro that checks if passed parameters are correct, i.e., all parameter types are unique,...
Definition named_parameter_check.hpp:80
Template magic to implement named parameters in cpp.
File containing the parameter types used by the KaMPIng library.
Factory methods for buffer wrappers.
Internal namespace marking the code that is not user-facing.
Definition collectives_helpers.hpp:20
auto make_nonblocking_result(RequestDataBuffer &&request, std::unique_ptr< std::tuple< Buffers... > > buffers_on_heap)
Factory for creating a kamping::NonBlockingResult.
Definition result.hpp:1308
Some functions and types simplifying/enabling the development of wrapped MPI calls in KaMPIng.