Logo AND Algorithmique Numérique Distribuée

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