Logo AND Algorithmique Numérique Distribuée

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