Fenix @develop
 
Loading...
Searching...
No Matches
group.hpp
1#ifndef FENIX_MPIXX_GROUP_HPP
2#define FENIX_MPIXX_GROUP_HPP
3
4#include <mpi.h>
5
6#include <utility>
7#include <vector>
8#include <array>
9
10#include "fenix/mpixx/util.hpp"
11
12namespace fenix::mpixx {
13
14class Comm; // Forward declaration
15
16// RAII wrapper for MPI_Group with move-only semantics
17// Owns an MPI_Group handle and automatically frees it on destruction.
18// Does NOT free MPI_GROUP_EMPTY or MPI_GROUP_NULL.
19// Accessors check MPI initialization state and return MPI_GROUP_NULL
20// if MPI is not initialized or has been finalized.
21class Group {
22 public:
23 // Construct from existing MPI_Group (takes ownership)
24 explicit Group(MPI_Group group) noexcept : group_(group) {}
25
26 // Default constructor creates MPI_GROUP_NULL
27 Group() noexcept : Group(MPI_GROUP_NULL) {}
28
29 // Implicit constructor from MPI_Comm (creates group from communicator)
30 Group(MPI_Comm comm);
31
32 // Implicit constructor from mpixx::Comm (creates group from communicator)
33 Group(const Comm& comm);
34
35 // Destructor automatically frees non-builtin groups
36 virtual ~Group() { free(); }
37
38 // Move semantics (frees old group before taking ownership)
39 Group& operator=(Group&& o) noexcept;
40 Group& operator=(MPI_Group group) { return *this = Group(group); }
41 Group(Group&& o) noexcept { *this = std::move(o); }
42
43 // Delete copy operations (move-only)
44 Group(const Group&) = delete;
45 Group& operator=(const Group&) = delete;
46
47 // Accessors
48 MPI_Group get() const noexcept {
49 return mpi_active() ? group_ : MPI_GROUP_NULL;
50 }
51
52 // Implicit conversion to MPI_Group
53 operator MPI_Group() const noexcept { return get(); }
54
55 explicit operator bool() const noexcept {
56 return get() != MPI_GROUP_NULL && get() != MPI_GROUP_EMPTY;
57 }
58
59 // Release ownership without freeing
60 MPI_Group release() noexcept;
61
62 // MPI group operations
63 int size() const;
64 int rank() const;
65
66 // Translate ranks from this group to another group
67 std::vector<int> translate_ranks(
68 const std::vector<int>& ranks1, const Group& group2
69 ) const;
70
71 // Translate all ranks from this group to another group
72 // Returns vector where result[i] = rank in group2 corresponding to rank i in
73 // this group
74 std::vector<int> translate_ranks(const Group& group2) const;
75
76 // Translate ranks from this group to another group (single rank)
77 int translate_rank(int rank1, const Group& group2) const;
78
79 // Check if this is a builtin group (NULL or EMPTY)
80 bool is_builtin() const noexcept;
81
82 // Free the group (safe even if group_ is MPI_GROUP_NULL or builtin)
83 virtual void free();
84
85 // ========== Group Comparison ==========
86
87 // Check if two groups are identical (MPI_IDENT)
88 bool operator==(const Group& other) const;
89 bool operator!=(const Group& other) const { return !(*this == other); }
90
91 // Check if two groups are similar (MPI_SIMILAR - same members, may differ in
92 // order)
93 bool similar(const Group& other) const;
94
95 // ========== Group Set Operations ==========
96
97 // Union: Create group containing all ranks from both groups
98 Group operator+(const Group& other) const;
99
100 // Intersection: Create group containing ranks in both groups
101 Group operator|(const Group& other) const;
102
103 // Difference: Create group containing ranks in this but not other
104 Group operator-(const Group& other) const;
105
106 // Compound assignment operators (modify this group in place)
107 Group& operator+=(const Group& other); // Union and assign
108 Group& operator|=(const Group& other); // Intersection and assign
109 Group& operator-=(const Group& other); // Difference and assign
110
111 // ========== Group Construction Factory Methods ==========
112
113 Group dup() const;
114
115 // Create group containing specified ranks from this group
116 Group incl(const std::vector<int>& ranks) const;
117
118 // Create group excluding specified ranks from this group
119 Group excl(const std::vector<int>& ranks) const;
120
121 // Create group containing ranks in given range from this group
122 // Each range is {first, last, stride}
123 Group range_incl(const std::vector<std::array<int, 3>>& ranges) const;
124
125 // Create group excluding ranks in given range from this group
126 Group range_excl(const std::vector<std::array<int, 3>>& ranges) const;
127
128 // Static versions operating on arbitrary source group
129
130 // Create group containing specified ranks from source group
131 static Group dup(MPI_Group source);
132
133 // Create group containing specified ranks from source group
134 static Group incl(MPI_Group source, const std::vector<int>& ranks);
135
136 // Create group excluding specified ranks from source group
137 static Group excl(MPI_Group source, const std::vector<int>& ranks);
138
139 // Create group containing ranks in given range
140 // Each range is {first, last, stride}
141 static Group range_incl(
142 MPI_Group source, const std::vector<std::array<int, 3>>& ranges
143 );
144
145 // Create group excluding ranks in given range
146 static Group range_excl(
147 MPI_Group source, const std::vector<std::array<int, 3>>& ranges
148 );
149
150 // Union of two groups
151 static Group union_of(const Group& group1, const Group& group2);
152
153 // Intersection of two groups
154 static Group intersection(const Group& group1, const Group& group2);
155
156 // Difference of two groups (ranks in group1 but not group2)
157 static Group difference(const Group& group1, const Group& group2);
158
159 private:
160 MPI_Group group_ = MPI_GROUP_NULL;
161
162 // Helper: Check if a given MPI_Group is builtin
163 static bool is_builtin_group(MPI_Group group) noexcept;
164
165 // Helper: Get comparison result between groups
166 static int compare(const Group& group1, const Group& group2);
167};
168
169// Non-owning reference to an MPI_Group
170// Does not free the group on destruction, only releases ownership.
171// Useful for storing groups that are owned elsewhere (e.g., builtins).
172// Unlike Group, GroupRef is copyable since it doesn't own the resource.
173class GroupRef : public Group {
174 public:
175 // Implicit constructor from MPI_Group
176 GroupRef(MPI_Group group = MPI_GROUP_NULL) : Group(group) {}
177 GroupRef(const Group& g) : Group(g.get()) {}
178 GroupRef(const GroupRef& other) : Group(other.get()) {}
179
180 GroupRef& operator=(const GroupRef& other) {
181 *this = other.get();
182 return *this;
183 }
184 GroupRef& operator=(const Group& g) {
185 *this = g.get();
186 return *this;
187 }
188 GroupRef& operator=(GroupRef&& other) {
189 if (this != &other) {
190 (void)release();
191 *this = other.release();
192 }
193 return *this;
194 }
195 GroupRef& operator=(MPI_Group group) {
196 (void)release();
197 // Directly assign to base class via Group's assignment operator
198 Group::operator=(Group(group));
199 return *this;
200 }
201
202 ~GroupRef() override { (void)release(); }
203};
204
205} // namespace fenix::mpixx
206
207#endif // FENIX_MPIXX_GROUP_HPP
Definition comm.hpp:16
Definition group.hpp:173
Definition group.hpp:21