Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
SMPI : add leak detection.
[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     (*newgroup)->add_f();
125   }
126   return MPI_SUCCESS;
127 }
128
129 int Group::group_union(MPI_Group group2, MPI_Group* newgroup)
130 {
131   int size1 = size_;
132   int size2 = group2->size();
133   for (int i = 0; i < size2; i++) {
134     s4u::Actor* actor = group2->actor(i);
135     int proc1 = this->rank(actor);
136     if (proc1 == MPI_UNDEFINED) {
137       size1++;
138     }
139   }
140   if (size1 == 0) {
141     *newgroup = MPI_GROUP_EMPTY;
142   } else {
143     *newgroup = new  Group(size1);
144     size2 = this->size();
145     for (int i = 0; i < size2; i++) {
146       s4u::Actor* actor1 = this->actor(i);
147       (*newgroup)->set_mapping(actor1, i);
148     }
149     for (int i = size2; i < size1; i++) {
150       s4u::Actor* actor = group2->actor(i - size2);
151       (*newgroup)->set_mapping(actor, i);
152     }
153     (*newgroup)->add_f();
154   }
155   return MPI_SUCCESS;
156 }
157
158 int Group::intersection(MPI_Group group2, MPI_Group* newgroup)
159 {
160   int size2 = group2->size();
161   for (int i = 0; i < size2; i++) {
162     s4u::Actor* actor = group2->actor(i);
163     int proc1 = this->rank(actor);
164     if (proc1 == MPI_UNDEFINED) {
165       size2--;
166     }
167   }
168   if (size2 == 0) {
169     *newgroup = MPI_GROUP_EMPTY;
170   } else {
171     *newgroup = new  Group(size2);
172     int j=0;
173     for (int i = 0; i < group2->size(); i++) {
174       s4u::Actor* actor = group2->actor(i);
175       int proc1 = this->rank(actor);
176       if (proc1 != MPI_UNDEFINED) {
177         (*newgroup)->set_mapping(actor, j);
178         j++;
179       }
180       (*newgroup)->add_f();
181     }
182   }
183   return MPI_SUCCESS;
184 }
185
186 int Group::difference(MPI_Group group2, MPI_Group* newgroup)
187 {
188   int newsize = size_;
189   int size2 = size_;
190   for (int i = 0; i < size2; i++) {
191     s4u::Actor* actor = this->actor(i);
192     int proc2 = group2->rank(actor);
193     if (proc2 != MPI_UNDEFINED) {
194       newsize--;
195     }
196   }
197   if (newsize == 0) {
198     *newgroup = MPI_GROUP_EMPTY;
199   } else {
200     *newgroup = new  Group(newsize);
201     for (int i = 0; i < size2; i++) {
202       s4u::Actor* actor = this->actor(i);
203       int proc2 = group2->rank(actor);
204       if (proc2 == MPI_UNDEFINED) {
205         (*newgroup)->set_mapping(actor, i);
206       }
207     }
208     (*newgroup)->add_f();
209   }
210   return MPI_SUCCESS;
211 }
212
213 int Group::excl(int n, const int *ranks, MPI_Group * newgroup){
214   int oldsize = size_;
215   int newsize = oldsize - n;
216   *newgroup = new  Group(newsize);
217   std::vector<bool> to_exclude(size_, false);
218   for (int i = 0; i < n; i++)
219     to_exclude[ranks[i]] = true;
220   int j = 0;
221   for (int i = 0; i < oldsize; i++) {
222     if (not to_exclude[i]) {
223       s4u::Actor* actor = this->actor(i);
224       (*newgroup)->set_mapping(actor, j);
225       j++;
226     }
227   }
228   (*newgroup)->add_f();
229   return MPI_SUCCESS;
230 }
231
232 static bool is_rank_in_range(int rank, int first, int last)
233 {
234   if (first < last)
235     return rank <= last;
236   else
237     return rank >= last;
238 }
239
240 int Group::range_incl(int n, int ranges[][3], MPI_Group * newgroup){
241   int newsize = 0;
242   for (int i = 0; i < n; i++) {
243     for (int rank = ranges[i][0];                    /* First */
244          rank >= 0 && rank < size_; /* Last */
245          ) {
246       newsize++;
247       if(rank == ranges[i][1]){/*already last ?*/
248         break;
249       }
250       rank += ranges[i][2]; /* Stride */
251       if (not is_rank_in_range(rank, ranges[i][0], ranges[i][1]))
252         break;
253     }
254   }
255   *newgroup = new  Group(newsize);
256   int j     = 0;
257   for (int i = 0; i < n; i++) {
258     for (int rank = ranges[i][0];                    /* First */
259          rank >= 0 && rank < size_; /* Last */
260          ) {
261       s4u::Actor* actor = this->actor(rank);
262       (*newgroup)->set_mapping(actor, j);
263       j++;
264       if(rank == ranges[i][1]){/*already last ?*/
265         break;
266       }
267       rank += ranges[i][2]; /* Stride */
268       if (not is_rank_in_range(rank, ranges[i][0], ranges[i][1]))
269         break;
270     }
271   }
272   (*newgroup)->add_f();
273   return MPI_SUCCESS;
274 }
275
276 int Group::range_excl(int n, int ranges[][3], MPI_Group * newgroup){
277   int newsize = size_;
278   for (int i = 0; i < n; i++) {
279     for (int rank = ranges[i][0];                    /* First */
280          rank >= 0 && rank < size_; /* Last */
281          ) {
282       newsize--;
283       if(rank == ranges[i][1]){/*already last ?*/
284         break;
285       }
286       rank += ranges[i][2]; /* Stride */
287       if (not is_rank_in_range(rank, ranges[i][0], ranges[i][1]))
288         break;
289     }
290   }
291   if (newsize == 0) {
292     *newgroup = MPI_GROUP_EMPTY;
293   } else {
294     *newgroup = new  Group(newsize);
295     int newrank = 0;
296     int oldrank = 0;
297     while (newrank < newsize) {
298       int add = 1;
299       for (int i = 0; i < n; i++) {
300         for (int rank = ranges[i][0]; rank >= 0 && rank < size_;) {
301           if(rank==oldrank){
302             add = 0;
303             break;
304           }
305           if(rank == ranges[i][1]){/*already last ?*/
306             break;
307           }
308           rank += ranges[i][2]; /* Stride */
309           if (not is_rank_in_range(rank, ranges[i][0], ranges[i][1]))
310             break;
311         }
312       }
313       if(add==1){
314         s4u::Actor* actor = this->actor(oldrank);
315         (*newgroup)->set_mapping(actor, newrank);
316         newrank++;
317       }
318       oldrank++;
319     }
320   }
321   (*newgroup)->add_f();
322   return MPI_SUCCESS;
323 }
324
325 MPI_Group Group::f2c(int id) {
326   if(id == -2) {
327     return MPI_GROUP_EMPTY;
328   } else if (F2C::lookup() != nullptr && id >= 0) {
329     return static_cast<MPI_Group>(F2C::lookup()->at(id));
330   } else {
331     return MPI_GROUP_NULL;
332   }
333 }
334
335 }
336 }