Logo AND Algorithmique Numérique Distribuée

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