Logo AND Algorithmique Numérique Distribuée

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