Logo AND Algorithmique Numérique Distribuée

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