Logo AND Algorithmique Numérique Distribuée

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