Logo AND Algorithmique Numérique Distribuée

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