1 /* Copyright (c) 2010-2017. The SimGrid Team. All rights reserved. */
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. */
6 #include "src/smpi/smpi_comm.hpp"
7 #include "src/smpi/smpi_group.hpp"
9 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;
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 */
25 Group::Group(int n) : size_(n)
27 rank_to_index_map_ = xbt_new(int, size_);
28 index_to_rank_map_ = xbt_dict_new_homogeneous(xbt_free_f);
30 for (int i = 0; i < size_; i++) {
31 rank_to_index_map_[i] = MPI_UNDEFINED;
35 Group::Group(MPI_Group origin)
37 if(origin != MPI_GROUP_NULL
38 && origin != MPI_GROUP_EMPTY)
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);
44 for (int i = 0; i < size_; i++) {
45 rank_to_index_map_[i] = origin->rank_to_index_map_[i];
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);
61 xbt_free(rank_to_index_map_);
62 xbt_dict_free(&index_to_rank_map_);
65 void Group::set_mapping(int index, int rank)
68 rank_to_index_map_[rank] = index;
69 if (index!=MPI_UNDEFINED ) {
70 int* val_rank = static_cast<int*>(xbt_malloc(sizeof(int)));
73 char * key = bprintf("%d", index);
74 xbt_dict_set(index_to_rank_map_, key, val_rank, nullptr);
80 int Group::index(int rank)
82 int index = MPI_UNDEFINED;
84 if (0 <= rank && rank < size_) {
85 index = rank_to_index_map_[rank];
90 int Group::rank(int index)
92 int * ptr_rank = nullptr;
93 if (this==MPI_GROUP_EMPTY)
95 char * key = bprintf("%d", index);
96 ptr_rank = static_cast<int*>(xbt_dict_get_or_null(index_to_rank_map_, key));
99 if (ptr_rank==nullptr)
100 return MPI_UNDEFINED;
109 void Group::unref(Group* group)
112 if (group->refcount_ <= 0) {
122 int Group::compare(MPI_Group group2)
127 if (size_ != group2->size()) {
128 result = MPI_UNEQUAL;
130 int sz = group2->size();
131 for (int i = 0; i < sz; i++) {
132 int index = this->index(i);
133 int rank = group2->rank(index);
134 if (rank == MPI_UNDEFINED) {
135 result = MPI_UNEQUAL;
139 result = MPI_SIMILAR;
146 int Group::incl(int n, int* ranks, MPI_Group* newgroup)
151 *newgroup = MPI_GROUP_EMPTY;
152 } else if (n == size_) {
154 if(this!= MPI_COMM_WORLD->group()
155 && this != MPI_COMM_SELF->group()
156 && this != MPI_GROUP_EMPTY)
159 *newgroup = new Group(n);
160 for (i = 0; i < n; i++) {
161 index = this->index(ranks[i]);
162 (*newgroup)->set_mapping(index, i);
168 int Group::group_union(MPI_Group group2, MPI_Group* newgroup)
171 int size2 = group2->size();
172 for (int i = 0; i < size2; i++) {
173 int proc2 = group2->index(i);
174 int proc1 = this->rank(proc2);
175 if (proc1 == MPI_UNDEFINED) {
180 *newgroup = MPI_GROUP_EMPTY;
182 *newgroup = new Group(size1);
183 size2 = this->size();
184 for (int i = 0; i < size2; i++) {
185 int proc1 = this->index(i);
186 (*newgroup)->set_mapping(proc1, i);
188 for (int i = size2; i < size1; i++) {
189 int proc2 = group2->index(i - size2);
190 (*newgroup)->set_mapping(proc2, i);
196 int Group::intersection(MPI_Group group2, MPI_Group* newgroup)
198 int size2 = group2->size();
199 for (int i = 0; i < size2; i++) {
200 int proc2 = group2->index(i);
201 int proc1 = this->rank(proc2);
202 if (proc1 == MPI_UNDEFINED) {
207 *newgroup = MPI_GROUP_EMPTY;
209 *newgroup = new Group(size2);
211 for (int i = 0; i < group2->size(); i++) {
212 int proc2 = group2->index(i);
213 int proc1 = this->rank(proc2);
214 if (proc1 != MPI_UNDEFINED) {
215 (*newgroup)->set_mapping(proc2, j);
223 int Group::difference(MPI_Group group2, MPI_Group* newgroup)
227 for (int i = 0; i < size2; i++) {
228 int proc1 = this->index(i);
229 int proc2 = group2->rank(proc1);
230 if (proc2 != MPI_UNDEFINED) {
235 *newgroup = MPI_GROUP_EMPTY;
237 *newgroup = new Group(newsize);
238 for (int i = 0; i < size2; i++) {
239 int proc1 = this->index(i);
240 int proc2 = group2->rank(proc1);
241 if (proc2 == MPI_UNDEFINED) {
242 (*newgroup)->set_mapping(proc1, i);
249 int Group::excl(int n, int *ranks, MPI_Group * newgroup){
251 int newsize = oldsize - n;
252 *newgroup = new Group(newsize);
253 int* to_exclude=xbt_new0(int, size_);
254 for (int i = 0; i < oldsize; i++)
256 for (int i = 0; i < n; i++)
257 to_exclude[ranks[i]]=1;
259 for (int i = 0; i < oldsize; i++) {
260 if(to_exclude[i]==0){
261 int index = this->index(i);
262 (*newgroup)->set_mapping(index, j);
266 xbt_free(to_exclude);
271 int Group::range_incl(int n, int ranges[][3], MPI_Group * newgroup){
273 for (int i = 0; i < n; i++) {
274 for (int rank = ranges[i][0]; /* First */
275 rank >= 0 && rank < size_; /* Last */
278 if(rank == ranges[i][1]){/*already last ?*/
281 rank += ranges[i][2]; /* Stride */
282 if (ranges[i][0] < ranges[i][1]) {
283 if (rank > ranges[i][1])
286 if (rank < ranges[i][1])
291 *newgroup = new Group(newsize);
293 for (int i = 0; i < n; i++) {
294 for (int rank = ranges[i][0]; /* First */
295 rank >= 0 && rank < size_; /* Last */
297 int index = this->index(rank);
298 (*newgroup)->set_mapping(index, j);
300 if(rank == ranges[i][1]){/*already last ?*/
303 rank += ranges[i][2]; /* Stride */
304 if (ranges[i][0] < ranges[i][1]) {
305 if (rank > ranges[i][1])
308 if (rank < ranges[i][1])
316 int Group::range_excl(int n, int ranges[][3], MPI_Group * newgroup){
318 for (int i = 0; i < n; i++) {
319 for (int rank = ranges[i][0]; /* First */
320 rank >= 0 && rank < size_; /* Last */
323 if(rank == ranges[i][1]){/*already last ?*/
326 rank += ranges[i][2]; /* Stride */
327 if (ranges[i][0] < ranges[i][1]) {
328 if (rank > ranges[i][1])
331 if (rank < ranges[i][1])
337 *newgroup = MPI_GROUP_EMPTY;
339 *newgroup = new Group(newsize);
342 while (newrank < newsize) {
344 for (int i = 0; i < n; i++) {
345 for (int rank = ranges[i][0]; rank >= 0 && rank < size_;) {
350 if(rank == ranges[i][1]){/*already last ?*/
353 rank += ranges[i][2]; /* Stride */
354 if (ranges[i][0]<ranges[i][1]){
355 if (rank > ranges[i][1])
358 if (rank < ranges[i][1])
364 int index = this->index(oldrank);
365 (*newgroup)->set_mapping(index, newrank);
374 MPI_Group Group::f2c(int id) {
376 return MPI_GROUP_EMPTY;
377 } else if(F2C::f2c_lookup() != nullptr && id >= 0) {
379 return static_cast<MPI_Group>(xbt_dict_get_or_null(F2C::f2c_lookup(), get_key(key, id)));
381 return static_cast<MPI_Group>(MPI_GROUP_NULL);