KaMPIng 0.1.2
Flexible and (near) zero-overhead C++ bindings for MPI
Loading...
Searching...
No Matches
isend.hpp
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
6// terms of the GNU Lesser General Public License as published by the Free
7// Software Foundation, either version 3 of the License, or (at your option) any
8// later version. KaMPIng is distributed in the hope that it will be useful, but
9// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
11// for more details.
12//
13// You should have received a copy of the GNU Lesser General Public License
14// along with KaMPIng. If not, see <https://www.gnu.org/licenses/>.
15
16#pragma once
17
18#include <type_traits>
19
20#include <kassert/kassert.hpp>
21#include <mpi.h>
22
23#include "kamping/communicator.hpp"
24#include "kamping/implementation_helpers.hpp"
29#include "kamping/p2p/helpers.hpp"
31#include "kamping/result.hpp"
32
33///// @addtogroup kamping_p2p
34/// @{
35
36// @brief Wrapper for \c MPI_Isend.
37///
38/// This wraps \c MPI_Isend. This operation sends the elements in the input buffer provided via \c
39/// kamping::send_buf() to the specified receiver rank using standard send mode without blocking. The call is associated
40/// with a \ref kamping::Request (either allocated by KaMPIng or provided by the user). Before accessing the result the
41/// user has to complete the request.
42///
43/// The following parameters are required:
44/// - \ref kamping::send_buf() containing the data that is sent.
45///
46/// - \ref kamping::destination() the receiving rank.
47///
48/// The following parameters are optional:
49/// - \ref kamping::send_count() specifying how many elements of the buffer are sent.
50/// If omitted, the size of the send buffer is used as a default. This parameter is mandatory if \ref
51/// kamping::send_type() is given.
52///
53/// - \ref kamping::send_type() specifying the \c MPI datatype to use as send type. If omitted, the \c MPI datatype is
54/// derived automatically based on send_buf's underlying \c value_type.
55///
56/// - \ref kamping::tag() the tag added to the message. Defaults to the communicator's default tag (\ref
57/// Communicator::default_tag()) if not present.
58///
59/// - \ref kamping::request() The request object to associate this operation with. Defaults to a library allocated
60/// request object, which can be access via the returned result.
61///
62/// - \ref kamping::send_mode() the send mode to use. Defaults to standard MPI_Send.
63///
64/// @tparam Args Automatically deduced template parameters.
65/// @param args All required and any number of the optional parameters described above.
66/// @return Result object wrapping the output parameters to be returned by value.
67///
68/// @see \ref docs/parameter_handling.md for general information about parameter handling in KaMPIng.
69/// <hr>
70/// \include{doc} docs/resize_policy.dox
71template <
72 template <typename...>
73 typename DefaultContainerType,
74 template <typename, template <typename...> typename>
75 typename... Plugins>
76template <typename... Args>
78 using namespace kamping::internal;
80 Args,
83 );
84
85 auto send_buf =
86 internal::select_parameter_type<internal::ParameterType::send_buf>(args...).construct_buffer_or_rebind();
87 using send_value_type = typename std::remove_reference_t<decltype(send_buf)>::value_type;
88
89 auto send_type = internal::determine_mpi_send_datatype<send_value_type>(args...);
90
92 auto send_count =
93 internal::select_parameter_type_or_default<internal::ParameterType::send_count, default_send_count_type>(
94 {},
95 args...
96 )
97 .construct_buffer_or_rebind();
98 if constexpr (has_to_be_computed<decltype(send_count)>) {
99 send_count.underlying() = asserting_cast<int>(send_buf.size());
100 }
101
102 auto const& destination = internal::select_parameter_type<internal::ParameterType::destination>(args...);
103 constexpr auto rank_type = std::remove_reference_t<decltype(destination)>::rank_type;
104 static_assert(
105 rank_type == RankType::value || rank_type == RankType::null,
106 "Please provide an explicit destination or destination(ranks::null)."
107 );
108 using default_request_param = decltype(kamping::request());
109 auto&& request_param =
110 internal::select_parameter_type_or_default<internal::ParameterType::request, default_request_param>(
111 std::tuple{},
112 args...
113 );
114
115 using default_tag_buf_type = decltype(kamping::tag(0));
116
117 auto&& tag_param = internal::select_parameter_type_or_default<internal::ParameterType::tag, default_tag_buf_type>(
118 std::tuple(this->default_tag()),
119 args...
120 );
121
122 // this ensures that the user does not try to pass MPI_ANY_TAG, which is not allowed for sends
123 static_assert(
124 std::remove_reference_t<decltype(tag_param)>::tag_type == TagType::value,
125 "Please provide a tag for the message."
126 );
127 int tag = tag_param.tag();
128 KASSERT(
130 "invalid tag " << tag << ", must be in range [0, " << Environment<>::tag_upper_bound() << "]"
131 );
132
133 using send_mode_obj_type =
137 using send_mode = typename std::remove_reference_t<send_mode_obj_type>::send_mode;
138
139 // RankType::null is valid, RankType::any is not.
140 KASSERT(is_valid_rank_in_comm(destination, *this, true, false), "Invalid destination rank.");
141
142 // store all parameters/buffers for which we have to ensure pointer stability until completion of the immediate MPI
143 // call on the heap.
144 auto buffers_on_heap = move_buffer_to_heap(std::move(send_buf));
145
146 auto* send_buf_ptr =
147 internal::select_parameter_type_in_tuple<internal::ParameterType::send_buf>(*buffers_on_heap).data();
148
149 if constexpr (std::is_same_v<send_mode, internal::standard_mode_t>) {
150 [[maybe_unused]] int err = MPI_Isend(
151 send_buf_ptr, // send_buf
152 send_count.get_single_element(), // send_count
153 send_type.get_single_element(), // send_type
154 destination.rank_signed(), // destination
155 tag, // tag
156 this->mpi_communicator(), // comm
157 request_param.underlying().request_ptr() // request
158 );
159 this->mpi_error_hook(err, "MPI_Isend");
160 } else if constexpr (std::is_same_v<send_mode, internal::buffered_mode_t>) {
161 [[maybe_unused]] int err = MPI_Ibsend(
162 send_buf_ptr, // send_buf
163 send_count.get_single_element(), // send_count
164 send_type.get_single_element(), // send_type
165 destination.rank_signed(), // destination
166 tag, // tag
167 this->mpi_communicator(), // comm
168 request_param.underlying().request_ptr() // request
169 );
170 this->mpi_error_hook(err, "MPI_Ibsend");
171 } else if constexpr (std::is_same_v<send_mode, internal::synchronous_mode_t>) {
172 [[maybe_unused]] int err = MPI_Issend(
173 send_buf_ptr, // send_buf
174 send_count.get_single_element(), // send_count
175 send_type.get_single_element(), // send_type
176 destination.rank_signed(), // destination
177 tag, // tag
178 this->mpi_communicator(), // comm
179 request_param.underlying().request_ptr() // request
180 );
181 this->mpi_error_hook(err, "MPI_Issend");
182 } else if constexpr (std::is_same_v<send_mode, internal::ready_mode_t>) {
183 [[maybe_unused]] int err = MPI_Irsend(
184 send_buf_ptr, // send_buf
185 send_count.get_single_element(), // send_count
186 send_type.get_single_element(), // send_type
187 destination.rank_signed(), // destination
188 tag, // tag
189 this->mpi_communicator(), // comm
190 request_param.underlying().request_ptr() // request
191 );
192 this->mpi_error_hook(err, "MPI_Irsend");
193 }
194 return internal::make_nonblocking_result<std::tuple<Args...>>(std::move(request_param), std::move(buffers_on_heap));
195}
196
197/// @brief Convenience wrapper for MPI_Ibsend. Calls \ref kamping::Communicator::isend() with the appropriate send mode
198/// set.
199template <
200 template <typename...>
201 typename DefaultContainerType,
202 template <typename, template <typename...> typename>
203 typename... Plugins>
204template <typename... Args>
206 return this->isend(std::forward<Args>(args)..., send_mode(send_modes::buffered));
207}
208
209/// @brief Convenience wrapper for MPI_Issend. Calls \ref kamping::Communicator::isend() with the appropriate send mode
210/// set.
211template <
212 template <typename...>
213 typename DefaultContainerType,
214 template <typename, template <typename...> typename>
215 typename... Plugins>
216template <typename... Args>
218 return this->isend(std::forward<Args>(args)..., send_mode(send_modes::synchronous));
219}
220
221/// @brief Convenience wrapper for MPI_Irsend. Calls \ref kamping::Communicator::isend() with the appropriate send mode
222/// set.
223template <
224 template <typename...>
225 typename DefaultContainerType,
226 template <typename, template <typename...> typename>
227 typename... Plugins>
228template <typename... Args>
230 return this->isend(std::forward<Args>(args)..., send_mode(send_modes::ready));
231}
232/// @}
Wrapper for MPI functions that don't require a communicator. If the template parameter init_finalize_...
Definition environment.hpp:52
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
auto send_mode(SendModeTag)
Passes the send mode parameter for point to point communication to the underlying call....
Definition named_parameters.hpp:1201
auto request()
Internally allocate a request object and return it to the user.
Definition named_parameters.hpp:1186
auto tag(internal::any_tag_t)
Indicates to use MPI_ANY_TAG as tag in the underlying call.
Definition named_parameters.hpp:1066
auto send_count(int count)
Passes count as send count to the underlying call.
Definition named_parameters.hpp:323
auto destination(int rank)
Passes rank as destination rank to the underlying call. This parameter is needed in point-to-point ex...
Definition named_parameters.hpp:1001
auto send_type(MPI_Datatype send_type)
Passes send_type as send type to the underlying call.
Definition named_parameters.hpp:1259
auto send_count_out()
Indicates to deduce the send count and return it to the caller as part of the underlying call's resul...
Definition named_parameters.hpp:349
auto send_buf(internal::ignore_t< Data > ignore)
Generates a dummy send buf that wraps a nullptr.
Definition named_parameters.hpp:53
auto ibsend(Args... args) const
Convenience wrapper for MPI_Ibsend. Calls kamping::Communicator::isend() with the appropriate send mo...
Definition isend.hpp:205
auto issend(Args... args) const
Convenience wrapper for MPI_Issend. Calls kamping::Communicator::isend() with the appropriate send mo...
Definition isend.hpp:217
auto isend(Args... args) const
Definition isend.hpp:77
auto irsend(Args... args) const
Convenience wrapper for MPI_Irsend. Calls kamping::Communicator::isend() with the appropriate send mo...
Definition isend.hpp:229
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
@ send_mode
Tag used to represent the send mode used by a send operation.
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:1310
Parameter objects return by named parameter factory functions.
Some functions and types simplifying/enabling the development of wrapped MPI calls in KaMPIng.
Parameter object for send_mode encapsulating the send mode compile-time tag.
Definition parameter_objects.hpp:478