Logo AND Algorithmique Numérique Distribuée

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