Logo AND Algorithmique Numérique Distribuée

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