KaMPIng 0.1.0
(Near) zero-overhead C++ MPI bindings.
Loading...
Searching...
No Matches
group.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 An abstraction around `MPI_Group`.
16
17#pragma once
18
19#include <kassert/kassert.hpp>
20#include <mpi.h>
21
24
25namespace kamping {
26
27/// @brief Describes the equality of two groups.
28enum class GroupEquality : uint8_t {
29 Identical, ///< The order and members of the two groups are the same.
30 Similar, ///< Only the members are the same, the order is different.
31 Unequal, ///< Otherwise
32 Invalid ///< Tried to convert an invalid value to a GroupEquality.
33};
34
35/// @brief A group of MPI processes.
36class Group {
37public:
38 /// @brief Constructs a new group from an existing MPI group.
39 Group(MPI_Group group, bool owning = false) : _group(group), _owns_group(owning) {}
40
41 Group(Group const&) = delete;
42 Group operator=(Group const&) = delete;
43
44 /// @brief Move constructor.
46 this->_group = other._group;
47 other._owns_group = false;
48 this->_owns_group = true;
49 }
50
51 /// @brief Move assignment.
53 this->_group = other._group;
54 other._owns_group = false;
55 this->_owns_group = true;
56 return *this;
57 }
58
59 /// @brief Constructs the group associated with a communicator.
60 template <typename Comm>
61 Group(Comm const& comm) : _owns_group(true) {
62 int err = MPI_Comm_group(comm.mpi_communicator(), &_group);
63 THROW_IF_MPI_ERROR(err, "MPI_Comm_group");
64 }
65
66 /// @brief Constructs an empty group.
67 /// @return An empty group.
68 [[nodiscard]] static Group empty() {
69 return Group(MPI_GROUP_EMPTY);
70 }
71
72 /// @brief Default destructor, freeing the encapsulated group if owned.
74 if (_owns_group) {
75 MPI_Group_free(&_group);
76 }
77 }
78
79 // TODO We need a safe tag for this -> move to another PR
80 // template <typename Comm>
81 // Comm create_comm(Comm const& comm) const {
82 // constexpr int safe_tag = 1337; // TODO
83 // MPI_Comm new_comm;
84 // MPI_Comm_group_create(comm, _group, safe_tag, &new_comm);
85 // return Comm(new_comm);
86 // }
87 // TODO _excl, _incl, _range_incl, _range_excl, and translate_ranks
88
89 /// @brief Compare two groups.
90 /// @param other The group to compare with.
91 /// @return The equality of the two groups (see \ref GroupEquality).
93 int result;
94 int err = MPI_Group_compare(_group, other._group, &result);
95 THROW_IF_MPI_ERROR(err, "MPI_Group_compare");
96
97 switch (result) {
98 case MPI_IDENT:
99 return GroupEquality::Identical;
100 case MPI_SIMILAR:
101 return GroupEquality::Similar;
102 case MPI_UNEQUAL:
103 return GroupEquality::Unequal;
104 default:
105 KASSERT(false, "MPI_Group_compare returned an unknown value");
106 return GroupEquality::Invalid;
107 }
108 }
109
110 /// @brief Compare two groups.
111 /// @param other The group to compare with.
112 /// @return True if the groups are identical; see \ref GroupEquality. False otherwise.
113 [[nodiscard]] bool is_identical(Group const& other) const {
114 return compare(other) == GroupEquality::Identical;
115 }
116
117 /// @brief Compare two groups.
118 /// @param other The group to compare with.
119 /// @return True if the groups are similar; see \ref GroupEquality. False otherwise.
120 [[nodiscard]] bool is_similar(Group const& other) const {
121 return compare(other) == GroupEquality::Similar;
122 }
123
124 /// @brief Compare two groups.
125 /// @param other The group to compare with.
126 /// @return True if the groups are identical; see \ref GroupEquality. False otherwise.
127 [[nodiscard]] bool has_same_ranks(Group const& other) const {
128 auto const result = compare(other);
129 return (result == GroupEquality::Identical) || (result == GroupEquality::Similar);
130 }
131
132 /// @brief Makes a group from the difference of two groups.
133 /// @param other The other group.
134 /// @return A group containing all the ranks of the first group that are not in the second group.
135 Group difference(Group const& other) const {
137 MPI_Group_difference(_group, other._group, &diff);
138 return Group(diff);
139 }
140
141 /// @brief Makes a group from the intersection of two groups.
142 /// @param other The other group.
143 /// @return A group containing only the ranks present in both groups.
146 int err = MPI_Group_intersection(_group, other._group, &inter);
147 THROW_IF_MPI_ERROR(err, "MPI_Group_intersection");
148 return Group(inter);
149 }
150
151 /// @brief Makes a group from the union of two groups.
152 /// @param other The other group.
153 /// @return A group containing all ranks present in either of the two groups.
154 /// @note The set_ prefix was choosen in order to avoid a name clash with the C++ keyword `union`.
155 Group set_union(Group const& other) const {
157 int err = MPI_Group_union(_group, other._group, &un);
158 THROW_IF_MPI_ERROR(err, "MPI_Group_union");
159 return Group(un);
160 }
161
162 /// @brief Get the number of ranks in the group.
163 /// @return The number of ranks in the group.
164 size_t size() const {
165 int size;
166 int err = MPI_Group_size(_group, &size);
167 THROW_IF_MPI_ERROR(err, "MPI_Group_size");
169 }
170
171 /// @brief Get the rank of the calling process in the group.
172 /// @return The rank of the calling process in the group.
173 size_t rank() const {
174 int rank;
175 int err = MPI_Group_rank(_group, &rank);
176 THROW_IF_MPI_ERROR(err, "MPI_Group_rank");
178 }
179
180private:
181 MPI_Group _group;
182 bool _owns_group;
183};
184
185} // namespace kamping
Helper functions that make casts safer.
A group of MPI processes.
Definition group.hpp:36
bool is_similar(Group const &other) const
Compare two groups.
Definition group.hpp:120
size_t rank() const
Get the rank of the calling process in the group.
Definition group.hpp:173
bool is_identical(Group const &other) const
Compare two groups.
Definition group.hpp:113
Group & operator=(Group &&other)
Move assignment.
Definition group.hpp:52
size_t size() const
Get the number of ranks in the group.
Definition group.hpp:164
Group set_union(Group const &other) const
Makes a group from the union of two groups.
Definition group.hpp:155
GroupEquality compare(Group const &other) const
Compare two groups.
Definition group.hpp:92
~Group()
Default destructor, freeing the encapsulated group if owned.
Definition group.hpp:73
Group(Comm const &comm)
Constructs the group associated with a communicator.
Definition group.hpp:61
Group intersection(Group const &other) const
Makes a group from the intersection of two groups.
Definition group.hpp:144
Group(Group &&other)
Move constructor.
Definition group.hpp:45
Group(MPI_Group group, bool owning=false)
Constructs a new group from an existing MPI group.
Definition group.hpp:39
Group difference(Group const &other) const
Makes a group from the difference of two groups.
Definition group.hpp:135
bool has_same_ranks(Group const &other) const
Compare two groups.
Definition group.hpp:127
static Group empty()
Constructs an empty group.
Definition group.hpp:68
STL-compatible allocator for requesting memory using the builtin MPI allocator.
Definition allocator.hpp:32
Code for error handling.
#define THROW_IF_MPI_ERROR(error_code, function)
Wrapper around THROWING_KASSERT for MPI errors.
Definition error_handling.hpp:33
GroupEquality
Describes the equality of two groups.
Definition group.hpp:28
@ Similar
Only the members are the same, the order is different.
@ Invalid
Tried to convert an invalid value to a GroupEquality.
@ Identical
The order and members of the two groups are the same.