Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
23c4809e80d2c2333e7d79924caae86ce906cdf6
[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 "smpi_group.hpp"
7 #include "smpi_comm.hpp"
8 #include <string>
9 #include <xbt/log.h>
10
11 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_group, smpi, "Logging specific to SMPI (group)");
12
13 simgrid::smpi::Group mpi_MPI_GROUP_EMPTY;
14 MPI_Group MPI_GROUP_EMPTY=&mpi_MPI_GROUP_EMPTY;
15
16 namespace simgrid{
17 namespace smpi{
18
19 Group::Group()
20 {
21   size_              = 0;       /* size */
22   refcount_          = 1;       /* refcount_: start > 0 so that this group never gets freed */
23 }
24
25 Group::Group(int n) : size_(n), rank_to_index_map_(size_)
26 {
27   refcount_ = 1;
28   for (int i              = 0; i < size_; i++)
29     rank_to_index_map_[i] = MPI_UNDEFINED;
30 }
31
32 Group::Group(MPI_Group origin)
33 {
34   if (origin != MPI_GROUP_NULL && origin != MPI_GROUP_EMPTY) {
35     size_              = origin->size();
36     refcount_          = 1;
37     rank_to_index_map_ = origin->rank_to_index_map_;
38
39     for (auto const& elm : origin->index_to_rank_map_) {
40       index_to_rank_map_.insert({elm.first, elm.second});
41     }
42   }
43 }
44
45 Group::~Group()
46 {
47   rank_to_index_map_.clear();
48 }
49
50 void Group::set_mapping(int index, int rank)
51 {
52   if (rank < size_) {
53     rank_to_index_map_[rank] = index;
54     if (index != MPI_UNDEFINED)
55       index_to_rank_map_.insert({index, rank});
56   }
57 }
58
59 int Group::index(int rank)
60 {
61   int index = MPI_UNDEFINED;
62
63   if (0 <= rank && rank < size_) {
64     index = rank_to_index_map_[rank];
65   }
66   return index;
67 }
68
69 int Group::rank(int index)
70 {
71   if (this == MPI_GROUP_EMPTY)
72     return MPI_UNDEFINED;
73   auto rank = index_to_rank_map_.find(index);
74   return rank == index_to_rank_map_.end() ? MPI_UNDEFINED : rank->second;
75 }
76
77 void Group::ref()
78 {
79   refcount_++;
80 }
81
82 void Group::unref(Group* group)
83 {
84   group->refcount_--;
85   if (group->refcount_ <= 0) {
86     delete group;
87   }
88 }
89
90 int Group::size()
91 {
92   return size_;
93 }
94
95 int Group::compare(MPI_Group group2)
96 {
97   int result;
98
99   result = MPI_IDENT;
100   if (size_ != group2->size()) {
101     result = MPI_UNEQUAL;
102   } else {
103     int sz = group2->size();
104     for (int i = 0; i < sz; i++) {
105       int index = this->index(i);
106       int rank = group2->rank(index);
107       if (rank == MPI_UNDEFINED) {
108         result = MPI_UNEQUAL;
109         break;
110       }
111       if (rank != i) {
112         result = MPI_SIMILAR;
113       }
114     }
115   }
116   return result;
117 }
118
119 int Group::incl(int n, int* ranks, MPI_Group* newgroup)
120 {
121   int i=0;
122   int index=0;
123   if (n == 0) {
124     *newgroup = MPI_GROUP_EMPTY;
125   } else if (n == size_) {
126     *newgroup = this;
127     if (this != MPI_COMM_WORLD->group() && this != MPI_COMM_SELF->group() && this != MPI_GROUP_EMPTY)
128       this->ref();
129   } else {
130     *newgroup = new Group(n);
131     for (i = 0; i < n; i++) {
132       index = this->index(ranks[i]);
133       (*newgroup)->set_mapping(index, i);
134     }
135   }
136   return MPI_SUCCESS;
137 }
138
139 int Group::group_union(MPI_Group group2, MPI_Group* newgroup)
140 {
141   int size1 = size_;
142   int size2 = group2->size();
143   for (int i = 0; i < size2; i++) {
144     int proc2 = group2->index(i);
145     int proc1 = this->rank(proc2);
146     if (proc1 == MPI_UNDEFINED) {
147       size1++;
148     }
149   }
150   if (size1 == 0) {
151     *newgroup = MPI_GROUP_EMPTY;
152   } else {
153     *newgroup = new  Group(size1);
154     size2 = this->size();
155     for (int i = 0; i < size2; i++) {
156       int proc1 = this->index(i);
157       (*newgroup)->set_mapping(proc1, i);
158     }
159     for (int i = size2; i < size1; i++) {
160       int proc2 = group2->index(i - size2);
161       (*newgroup)->set_mapping(proc2, i);
162     }
163   }
164   return MPI_SUCCESS;
165 }
166
167 int Group::intersection(MPI_Group group2, MPI_Group* newgroup)
168 {
169   int size2 = group2->size();
170   for (int i = 0; i < size2; i++) {
171     int proc2 = group2->index(i);
172     int proc1 = this->rank(proc2);
173     if (proc1 == MPI_UNDEFINED) {
174       size2--;
175     }
176   }
177   if (size2 == 0) {
178     *newgroup = MPI_GROUP_EMPTY;
179   } else {
180     *newgroup = new  Group(size2);
181     int j=0;
182     for (int i = 0; i < group2->size(); i++) {
183       int proc2 = group2->index(i);
184       int proc1 = this->rank(proc2);
185       if (proc1 != MPI_UNDEFINED) {
186         (*newgroup)->set_mapping(proc2, j);
187         j++;
188       }
189     }
190   }
191   return MPI_SUCCESS;
192 }
193
194 int Group::difference(MPI_Group group2, MPI_Group* newgroup)
195 {
196   int newsize = size_;
197   int size2 = size_;
198   for (int i = 0; i < size2; i++) {
199     int proc1 = this->index(i);
200     int proc2 = group2->rank(proc1);
201     if (proc2 != MPI_UNDEFINED) {
202       newsize--;
203     }
204   }
205   if (newsize == 0) {
206     *newgroup = MPI_GROUP_EMPTY;
207   } else {
208     *newgroup = new  Group(newsize);
209     for (int i = 0; i < size2; i++) {
210       int proc1 = this->index(i);
211       int proc2 = group2->rank(proc1);
212       if (proc2 == MPI_UNDEFINED) {
213         (*newgroup)->set_mapping(proc1, i);
214       }
215     }
216   }
217   return MPI_SUCCESS;
218 }
219
220 int Group::excl(int n, int *ranks, MPI_Group * newgroup){
221   int oldsize = size_;
222   int newsize = oldsize - n;
223   *newgroup = new  Group(newsize);
224   int* to_exclude = new int[size_];
225   for (int i     = 0; i < oldsize; i++)
226     to_exclude[i]=0;
227   for (int i            = 0; i < n; i++)
228     to_exclude[ranks[i]]=1;
229   int j = 0;
230   for (int i = 0; i < oldsize; i++) {
231     if(to_exclude[i]==0){
232       int index = this->index(i);
233       (*newgroup)->set_mapping(index, j);
234       j++;
235     }
236   }
237   delete[] to_exclude;
238   return MPI_SUCCESS;
239
240 }
241
242 int Group::range_incl(int n, int ranges[][3], MPI_Group * newgroup){
243   int newsize = 0;
244   for (int i = 0; i < n; i++) {
245     for (int rank = ranges[i][0];                    /* First */
246          rank >= 0 && rank < size_; /* Last */
247          ) {
248       newsize++;
249       if(rank == ranges[i][1]){/*already last ?*/
250         break;
251       }
252       rank += ranges[i][2]; /* Stride */
253       if (ranges[i][0] < ranges[i][1]) {
254         if (rank > ranges[i][1])
255           break;
256       } else {
257         if (rank < ranges[i][1])
258           break;
259       }
260     }
261   }
262   *newgroup = new  Group(newsize);
263   int j     = 0;
264   for (int i = 0; i < n; i++) {
265     for (int rank = ranges[i][0];                    /* First */
266          rank >= 0 && rank < size_; /* Last */
267          ) {
268       int index = this->index(rank);
269       (*newgroup)->set_mapping(index, j);
270       j++;
271       if(rank == ranges[i][1]){/*already last ?*/
272         break;
273       }
274       rank += ranges[i][2]; /* Stride */
275       if (ranges[i][0] < ranges[i][1]) {
276         if (rank > ranges[i][1])
277           break;
278       } else {
279         if (rank < ranges[i][1])
280           break;
281       }
282     }
283   }
284   return MPI_SUCCESS;
285 }
286
287 int Group::range_excl(int n, int ranges[][3], MPI_Group * newgroup){
288   int newsize = size_;
289   for (int i = 0; i < n; i++) {
290     for (int rank = ranges[i][0];                    /* First */
291          rank >= 0 && rank < size_; /* Last */
292          ) {
293       newsize--;
294       if(rank == ranges[i][1]){/*already last ?*/
295         break;
296       }
297       rank += ranges[i][2]; /* Stride */
298       if (ranges[i][0] < ranges[i][1]) {
299         if (rank > ranges[i][1])
300           break;
301       } else {
302         if (rank < ranges[i][1])
303           break;
304       }
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 (ranges[i][0]<ranges[i][1]){
326             if (rank > ranges[i][1])
327               break;
328           }else{
329             if (rank < ranges[i][1])
330               break;
331           }
332         }
333       }
334       if(add==1){
335         int index = this->index(oldrank);
336         (*newgroup)->set_mapping(index, newrank);
337         newrank++;
338       }
339       oldrank++;
340     }
341   }
342   return MPI_SUCCESS;
343 }
344
345 MPI_Group Group::f2c(int id) {
346   if(id == -2) {
347     return MPI_GROUP_EMPTY;
348   } else if(F2C::f2c_lookup() != nullptr && id >= 0) {
349     char key[KEY_SIZE];
350     return static_cast<MPI_Group>(F2C::f2c_lookup()->at(get_key(key, id)));
351   } else {
352     return static_cast<MPI_Group>(MPI_GROUP_NULL);
353   }
354 }
355
356 }
357 }