Skip to content
New issue

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

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

Already on GitHub? # 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 2 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 send_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