Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Fix Group::group_union().
[simgrid.git] / src / smpi / mpi / smpi_group.cpp
1 /* Copyright (c) 2010-2021. The SimGrid Team. All rights reserved.          */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #include "simgrid/s4u/Actor.hpp"
7 #include "smpi_group.hpp"
8 #include "smpi_comm.hpp"
9 #include <string>
10
11 simgrid::smpi::Group smpi_MPI_GROUP_EMPTY;
12 extern XBT_PRIVATE MPI_Comm MPI_COMM_UNINITIALIZED;
13
14 namespace simgrid{
15 namespace smpi{
16
17 Group::Group(const Group* origin)
18 {
19   if (origin != MPI_GROUP_NULL && origin != MPI_GROUP_EMPTY) {
20     // FIXME: cheinrich: There is no such thing as an index any more; the two maps should be removed
21     index_to_rank_map_ = origin->index_to_rank_map_;
22     rank_to_actor_map_ = origin->rank_to_actor_map_;
23     actor_to_rank_map_ = origin->actor_to_rank_map_;
24   }
25 }
26
27 void Group::set_mapping(s4u::Actor* actor, int rank)
28 {
29   if (0 <= rank && rank < size()) {
30     int index = actor->get_pid();
31     if ((unsigned)index >= index_to_rank_map_.size())
32       index_to_rank_map_.resize(index + 1, MPI_UNDEFINED);
33     index_to_rank_map_[index] = rank;
34     rank_to_actor_map_[rank] = actor;
35     actor_to_rank_map_.insert({actor, rank});
36   }
37 }
38
39 int Group::rank(int index) const
40 {
41   int rank;
42   if (0 <= index && (unsigned)index < index_to_rank_map_.size())
43     rank = index_to_rank_map_[index];
44   else
45     rank = MPI_UNDEFINED;
46
47   return rank;
48 }
49
50 s4u::Actor* Group::actor(int rank) const
51 {
52   if (0 <= rank && rank < size())
53     return rank_to_actor_map_[rank];
54   else
55     return nullptr;
56 }
57
58 int Group::rank(s4u::Actor* actor) const
59 {
60   auto iterator = actor_to_rank_map_.find(actor);
61   //I'm not in the communicator ... but maybe my parent is ?
62   if (iterator == actor_to_rank_map_.end())
63     iterator = actor_to_rank_map_.find(s4u::Actor::by_pid(actor->get_ppid()).get());
64   return (iterator == actor_to_rank_map_.end()) ? MPI_UNDEFINED : (*iterator).second;
65 }
66
67 void Group::ref()
68 {
69   refcount_++;
70 }
71
72 void Group::unref(Group* group)
73 {
74   group->refcount_--;
75   if (group->refcount_ <= 0) {
76     if (simgrid::smpi::F2C::lookup() != nullptr)
77       F2C::free_f(group->f2c_id());
78     delete group;
79   }
80 }
81
82 int Group::compare(MPI_Group group2) const
83 {
84   int result;
85
86   result = MPI_IDENT;
87   if (size() != group2->size()) {
88     result = MPI_UNEQUAL;
89   } else {
90     for (int i = 0; i < size(); i++) {
91       int rank = group2->rank(actor(i));
92       if (rank == MPI_UNDEFINED) {
93         result = MPI_UNEQUAL;
94         break;
95       }
96       if (rank != i) {
97         result = MPI_SIMILAR;
98       }
99     }
100   }
101   return result;
102 }
103
104 int Group::incl(int n, const int* ranks, MPI_Group* newgroup) const
105 {
106   if (n == 0) {
107     *newgroup = MPI_GROUP_EMPTY;
108     return MPI_SUCCESS;
109   }
110
111   *newgroup = new Group(n);
112   for (int i = 0; i < n; i++) {
113     s4u::Actor* actor = this->actor(ranks[i]);
114     (*newgroup)->set_mapping(actor, i);
115   }
116   (*newgroup)->add_f();
117   return MPI_SUCCESS;
118 }
119
120 int Group::group_union(MPI_Group group2, MPI_Group* newgroup) const
121 {
122   std::vector<int> to_incl;
123   for (int i = 0; i < group2->size(); i++) {
124     s4u::Actor* actor = group2->actor(i);
125     if (rank(actor) == MPI_UNDEFINED)
126       to_incl.push_back(i);
127   }
128
129   int newsize = size() + static_cast<int>(to_incl.size());
130   if (newsize == 0) {
131     *newgroup = MPI_GROUP_EMPTY;
132     return MPI_SUCCESS;
133   }
134
135   *newgroup = new Group(newsize);
136   int i;
137   for (i = 0; i < size(); i++) {
138     s4u::Actor* actor1 = actor(i);
139     (*newgroup)->set_mapping(actor1, i);
140   }
141   for (int j : to_incl) {
142     s4u::Actor* actor2 = group2->actor(j);
143     (*newgroup)->set_mapping(actor2, i);
144     i++;
145   }
146   (*newgroup)->add_f();
147   return MPI_SUCCESS;
148 }
149
150 int Group::intersection(MPI_Group group2, MPI_Group* newgroup) const
151 {
152   int size2 = group2->size();
153   for (int i = 0; i < size2; i++) {
154     s4u::Actor* actor = group2->actor(i);
155     int proc1 = this->rank(actor);
156     if (proc1 == MPI_UNDEFINED) {
157       size2--;
158     }
159   }
160   if (size2 == 0) {
161     *newgroup = MPI_GROUP_EMPTY;
162   } else {
163     *newgroup = new  Group(size2);
164     int j=0;
165     for (int i = 0; i < group2->size(); i++) {
166       s4u::Actor* actor = group2->actor(i);
167       int proc1 = this->rank(actor);
168       if (proc1 != MPI_UNDEFINED) {
169         (*newgroup)->set_mapping(actor, j);
170         j++;
171       }
172     }
173     if((*newgroup)!=MPI_GROUP_EMPTY)
174       (*newgroup)->add_f();
175   }
176   return MPI_SUCCESS;
177 }
178
179 int Group::difference(MPI_Group group2, MPI_Group* newgroup) const
180 {
181   std::vector<int> to_incl;
182   for (int i = 0; i < size(); i++) {
183     s4u::Actor* actor = this->actor(i);
184     if (group2->rank(actor) == MPI_UNDEFINED)
185       to_incl.push_back(i);
186   }
187
188   if (to_incl.empty()) {
189     *newgroup = MPI_GROUP_EMPTY;
190     return MPI_SUCCESS;
191   }
192
193   int newsize = static_cast<int>(to_incl.size());
194   *newgroup   = new Group(newsize);
195   for (int i = 0; i < newsize; i++) {
196     s4u::Actor* actor = group2->actor(to_incl[i]);
197     (*newgroup)->set_mapping(actor, i);
198   }
199   (*newgroup)->add_f();
200   return MPI_SUCCESS;
201 }
202
203 int Group::excl(int n, const int* ranks, MPI_Group* newgroup) const
204 {
205   if (n == size()) {
206     *newgroup = MPI_GROUP_EMPTY;
207     return MPI_SUCCESS;
208   }
209
210   std::vector<bool> to_excl(size(), false);
211   for (int i = 0; i < n; i++)
212     to_excl[ranks[i]] = true;
213
214   int newsize = size() - n;
215   *newgroup   = new Group(newsize);
216   int j = 0;
217   for (int i = 0; i < size(); i++) {
218     if (not to_excl[i]) {
219       s4u::Actor* actor = this->actor(i);
220       (*newgroup)->set_mapping(actor, j);
221       j++;
222     }
223   }
224   (*newgroup)->add_f();
225   return MPI_SUCCESS;
226 }
227
228 static bool is_rank_in_range(int rank, int first, int last)
229 {
230   return (first <= rank && rank <= last) || (first >= rank && rank >= last);
231 }
232
233 int Group::range_incl(int n, int ranges[][3], MPI_Group* newgroup) const
234 {
235   std::vector<int> to_incl;
236   for (int i = 0; i < n; i++)
237     for (int j = ranges[i][0]; j >= 0 && j < size() && is_rank_in_range(j, ranges[i][0], ranges[i][1]);
238          j += ranges[i][2])
239       to_incl.push_back(j);
240
241   if (to_incl.empty()) {
242     *newgroup = MPI_GROUP_EMPTY;
243     return MPI_SUCCESS;
244   }
245
246   int newsize = static_cast<int>(to_incl.size());
247   *newgroup   = new Group(newsize);
248
249   for (int i = 0; i < newsize; i++) {
250     s4u::Actor* actor = this->actor(to_incl[i]);
251     (*newgroup)->set_mapping(actor, i);
252   }
253   (*newgroup)->add_f();
254   return MPI_SUCCESS;
255 }
256
257 int Group::range_excl(int n, int ranges[][3], MPI_Group* newgroup) const
258 {
259   std::vector<bool> to_excl(size(), false);
260   int newsize = size();
261   for (int i = 0; i < n; i++) {
262     for (int j = ranges[i][0]; j >= 0 && j < size() && is_rank_in_range(j, ranges[i][0], ranges[i][1]);
263          j += ranges[i][2]) {
264       to_excl[j] = true;
265       newsize--;
266     }
267   }
268   if (newsize == 0) {
269     *newgroup = MPI_GROUP_EMPTY;
270     return MPI_SUCCESS;
271   }
272
273   *newgroup = new Group(newsize);
274   int j     = 0;
275   for (int i = 0; i < size(); i++) {
276     if (not to_excl[i]) {
277       s4u::Actor* actor = this->actor(i);
278       (*newgroup)->set_mapping(actor, j);
279       j++;
280     }
281   }
282   (*newgroup)->add_f();
283   return MPI_SUCCESS;
284 }
285
286 MPI_Group Group::f2c(int id) {
287   if(id == -2) {
288     return MPI_GROUP_EMPTY;
289   } else if (F2C::lookup() != nullptr && id >= 0) {
290     return static_cast<MPI_Group>(F2C::lookup()->at(id));
291   } else {
292     return MPI_GROUP_NULL;
293   }
294 }
295
296 }
297 }