Logo AND Algorithmique Numérique Distribuée

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