Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add named parameters send_tag and recv_tag. #762

Merged
merged 3 commits into from
Feb 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/kamping/named_parameter_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ enum class ParameterType {
request, ///< Tag used to represent an \c MPI_Request.
root, ///< Tag used to represent the root PE in a \c MPI collectives call.
tag, ///< Tag used to represent the message tag in a \c MPI call.
send_tag, ///< Tag used to represent the message send tag in a \c MPI call.
recv_tag, ///< Tag used to represent the message recv tag in a \c MPI call.
send_mode, ///< Tag used to represent the send mode used by a send operation.
values_on_rank_0, ///< Tag used to represent the value of the exclusive scan
///< operation on rank 0.
Expand Down
64 changes: 63 additions & 1 deletion include/kamping/named_parameters.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1076,7 +1076,7 @@ inline auto tag(int value) {
return internal::TagParam<internal::TagType::value>{value};
}

/// @brief Converts the passed enum \p value to its integer representaiton and passes this value to the underlying call.
/// @brief Converts the passed enum \p value to its integer representation and passes this value to the underlying call.
///
/// @param value The tag value.
/// @return The corresponding parameter object.
Expand All @@ -1090,6 +1090,68 @@ inline auto tag(EnumType value) {
return tag(static_cast<int>(value));
}

/// @brief Indicates to use \c MPI_ANY_TAG as send tag in the underlying call.
///
/// @return The corresponding parameter object.
/// @see \ref docs/parameter_handling.md for general information about parameter handling in KaMPIng.
inline auto send_tag(internal::any_tag_t) {
return internal::TagParam<internal::TagType::any, internal::ParameterType::send_tag>{};
}

/// @brief Passes \p value as send tag to the underlying call.
///
/// @param value The tag value.
/// @return The corresponding parameter object.
/// @see \ref docs/parameter_handling.md for general information about parameter handling in KaMPIng.
inline auto send_tag(int value) {
return internal::TagParam<internal::TagType::value, internal::ParameterType::send_tag>{value};
}

/// @brief Converts the passed enum \p value to its integer representation and passes this value to the underlying call.
///
/// @param value The send tag value.
/// @return The corresponding parameter object.
/// @see \ref docs/parameter_handling.md for general information about parameter handling in KaMPIng.
template <typename EnumType, typename = std::enable_if_t<std::is_enum_v<EnumType>>>
inline auto send_tag(EnumType value) {
static_assert(
std::is_convertible_v<std::underlying_type_t<EnumType>, int>,
"The underlying enum type must be implicitly convertible to int."
);
return send_tag(static_cast<int>(value));
}

/// @brief Indicates to use \c MPI_ANY_TAG as recv tag in the underlying call.
///
/// @return The corresponding parameter object.
/// @see \ref docs/parameter_handling.md for general information about parameter handling in KaMPIng.
inline auto recv_tag(internal::any_tag_t) {
return internal::TagParam<internal::TagType::any, internal::ParameterType::recv_tag>{};
}

/// @brief Passes \p value as recv tag to the underlying call.
///
/// @param value The tag value.
/// @return The corresponding parameter object.
/// @see \ref docs/parameter_handling.md for general information about parameter handling in KaMPIng.
inline auto recv_tag(int value) {
return internal::TagParam<internal::TagType::value, internal::ParameterType::recv_tag>{value};
}

/// @brief Converts the passed enum \p value to its integer representation and passes this value to the underlying call.
///
/// @param value The recv tag value.
/// @return The corresponding parameter object.
/// @see \ref docs/parameter_handling.md for general information about parameter handling in KaMPIng.
template <typename EnumType, typename = std::enable_if_t<std::is_enum_v<EnumType>>>
inline auto recv_tag(EnumType value) {
static_assert(
std::is_convertible_v<std::underlying_type_t<EnumType>, int>,
"The underlying enum type must be implicitly convertible to int."
);
return recv_tag(static_cast<int>(value));
}

/// @brief Passes a request handle to the underlying MPI call.
/// @param request The request handle.
/// @return The corresponding parameter object.
Expand Down
19 changes: 10 additions & 9 deletions include/kamping/parameter_objects.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -509,17 +509,18 @@ enum class TagType {

/// @brief Encapsulates a message tag.
/// @tparam The type of the tag.
template <TagType tag_type>
/// @tparam The parameter type associated with the tag parameter object. Defaults to \ref ParameterType::tag.
template <TagType tag_type, ParameterType parameter_type = ParameterType::tag>
class TagParam {};

/// @brief Encapsulates a message tag. Specialization if an explicit tag value is provided.
template <>
class TagParam<TagType::value> : private CopyMoveEnabler<> {
template <ParameterType parameter_type_>
class TagParam<TagType::value, parameter_type_> : private CopyMoveEnabler<> {
public:
/// @param tag The tag.
TagParam(int tag) : _tag_value(tag) {}
static constexpr ParameterType parameter_type = ParameterType::tag; ///< The parameter type.
static constexpr TagType tag_type = TagType::value; ///< The tag type.
static constexpr ParameterType parameter_type = parameter_type_; ///< The parameter type.
static constexpr TagType tag_type = TagType::value; ///< The tag type.
/// @return The tag.
[[nodiscard]] int tag() const {
return _tag_value;
Expand All @@ -537,11 +538,11 @@ class TagParam<TagType::value> : private CopyMoveEnabler<> {
};

/// @brief Encapsulates a message tag. Specialization if the value is MPI_ANY_TAG.
template <>
class TagParam<TagType::any> : private CopyMoveEnabler<> {
template <ParameterType parameter_type_>
class TagParam<TagType::any, parameter_type_> : private CopyMoveEnabler<> {
public:
static constexpr ParameterType parameter_type = ParameterType::tag; ///< The parameter type.
static constexpr TagType tag_type = TagType::any; ///< The tag type.
static constexpr ParameterType parameter_type = parameter_type_; ///< The parameter type.
static constexpr TagType tag_type = TagType::any; ///< The tag type.
/// @return The tag.
[[nodiscard]] int tag() const {
return MPI_ANY_TAG;
Expand Down
102 changes: 102 additions & 0 deletions tests/named_parameters_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1203,6 +1203,108 @@ TEST(ParameterFactoriesTest, tag_enum_class) {
}
}

TEST(ParameterFactoriesTest, send_tag_basics) {
{
auto tag_obj = send_tag(22);
EXPECT_EQ(tag_obj.tag(), 22);
EXPECT_EQ(decltype(tag_obj)::parameter_type, ParameterType::send_tag);
EXPECT_EQ(decltype(tag_obj)::tag_type, TagType::value);
}
{
auto tag_obj = send_tag(tags::any);
EXPECT_EQ(tag_obj.tag(), MPI_ANY_TAG);
EXPECT_EQ(decltype(tag_obj)::tag_type, TagType::any);
}
}

TEST(ParameterFactoriesTest, send_tag_enum) {
enum Tags : int {
type_a = 27,
type_b = 3,
};
{
auto tag_obj = send_tag(Tags::type_a);
EXPECT_EQ(tag_obj.tag(), 27);
EXPECT_EQ(decltype(tag_obj)::parameter_type, ParameterType::send_tag);
EXPECT_EQ(decltype(tag_obj)::tag_type, TagType::value);
}
{
auto tag_obj = send_tag(Tags::type_b);
EXPECT_EQ(tag_obj.tag(), 3);
EXPECT_EQ(decltype(tag_obj)::parameter_type, ParameterType::send_tag);
EXPECT_EQ(decltype(tag_obj)::tag_type, TagType::value);
}
}

TEST(ParameterFactoriesTest, send_tag_enum_class) {
enum class Tags {
type_a = 27,
type_b = 3,
};
{
auto tag_obj = send_tag(Tags::type_a);
EXPECT_EQ(tag_obj.tag(), 27);
EXPECT_EQ(decltype(tag_obj)::tag_type, TagType::value);
}
{
auto tag_obj = send_tag(Tags::type_b);
EXPECT_EQ(tag_obj.tag(), 3);
EXPECT_EQ(decltype(tag_obj)::parameter_type, ParameterType::send_tag);
EXPECT_EQ(decltype(tag_obj)::tag_type, TagType::value);
}
}

TEST(ParameterFactoriesTest, recv_tag_basics) {
{
auto tag_obj = recv_tag(22);
EXPECT_EQ(tag_obj.tag(), 22);
EXPECT_EQ(decltype(tag_obj)::parameter_type, ParameterType::recv_tag);
EXPECT_EQ(decltype(tag_obj)::tag_type, TagType::value);
}
{
auto tag_obj = recv_tag(tags::any);
EXPECT_EQ(tag_obj.tag(), MPI_ANY_TAG);
EXPECT_EQ(decltype(tag_obj)::tag_type, TagType::any);
}
}

TEST(ParameterFactoriesTest, recv_tag_enum) {
enum Tags : int {
type_a = 27,
type_b = 3,
};
{
auto tag_obj = recv_tag(Tags::type_a);
EXPECT_EQ(tag_obj.tag(), 27);
EXPECT_EQ(decltype(tag_obj)::parameter_type, ParameterType::recv_tag);
EXPECT_EQ(decltype(tag_obj)::tag_type, TagType::value);
}
{
auto tag_obj = recv_tag(Tags::type_b);
EXPECT_EQ(tag_obj.tag(), 3);
EXPECT_EQ(decltype(tag_obj)::parameter_type, ParameterType::recv_tag);
EXPECT_EQ(decltype(tag_obj)::tag_type, TagType::value);
}
}

TEST(ParameterFactoriesTest, recv_tag_enum_class) {
enum class Tags {
type_a = 27,
type_b = 3,
};
{
auto tag_obj = recv_tag(Tags::type_a);
EXPECT_EQ(tag_obj.tag(), 27);
EXPECT_EQ(decltype(tag_obj)::tag_type, TagType::value);
}
{
auto tag_obj = recv_tag(Tags::type_b);
EXPECT_EQ(tag_obj.tag(), 3);
EXPECT_EQ(decltype(tag_obj)::parameter_type, ParameterType::recv_tag);
EXPECT_EQ(decltype(tag_obj)::tag_type, TagType::value);
}
}

TEST(ParameterFactoriesTest, status_basics) {
{
auto status_obj = status(kamping::ignore<>).construct_buffer_or_rebind();
Expand Down
Loading