Logo AND Algorithmique Numérique Distribuée

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