Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Minor cleanups (useless stuff).
[simgrid.git] / src / smpi / mpi / smpi_group.cpp
1 /* Copyright (c) 2010-2021. 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 "simgrid/s4u/Actor.hpp"
7 #include "smpi_group.hpp"
8 #include "smpi_comm.hpp"
9 #include <string>
10
11 simgrid::smpi::Group smpi_MPI_GROUP_EMPTY;
12
13 namespace simgrid{
14 namespace smpi{
15
16 Group::Group(const Group* origin)
17 {
18   if (origin != MPI_GROUP_NULL && origin != MPI_GROUP_EMPTY) {
19     // FIXME: cheinrich: There is no such thing as an index any more; the two maps should be removed
20     index_to_rank_map_ = origin->index_to_rank_map_;
21     rank_to_actor_map_ = origin->rank_to_actor_map_;
22     actor_to_rank_map_ = origin->actor_to_rank_map_;
23   }
24 }
25
26 void Group::set_mapping(s4u::Actor* actor, int rank)
27 {
28   if (0 <= rank && rank < size()) {
29     int index = actor->get_pid();
30     if ((unsigned)index >= index_to_rank_map_.size())
31       index_to_rank_map_.resize(index + 1, MPI_UNDEFINED);
32     index_to_rank_map_[index] = rank;
33     rank_to_actor_map_[rank] = actor;
34     actor_to_rank_map_.insert({actor, rank});
35   }
36 }
37
38 int Group::rank(int index) const
39 {
40   int rank;
41   if (0 <= index && (unsigned)index < index_to_rank_map_.size())
42     rank = index_to_rank_map_[index];
43   else
44     rank = MPI_UNDEFINED;
45
46   return rank;
47 }
48
49 s4u::Actor* Group::actor(int rank) const
50 {
51   if (0 <= rank && rank < size())
52     return rank_to_actor_map_[rank];
53   else
54     return nullptr;
55 }
56
57 int Group::rank(s4u::Actor* actor) const
58 {
59   auto iterator = actor_to_rank_map_.find(actor);
60   //I'm not in the communicator ... but maybe my parent is ?
61   if (iterator == actor_to_rank_map_.end())
62     iterator = actor_to_rank_map_.find(s4u::Actor::by_pid(actor->get_ppid()).get());
63   return (iterator == actor_to_rank_map_.end()) ? MPI_UNDEFINED : (*iterator).second;
64 }
65
66 void Group::ref()
67 {
68   refcount_++;
69 }
70
71 void Group::unref(Group* group)
72 {
73   group->refcount_--;
74   if (group->refcount_ <= 0) {
75     if (simgrid::smpi::F2C::lookup() != nullptr)
76       F2C::free_f(group->f2c_id());
77     delete group;
78   }
79 }
80
81 int Group::compare(const Group* group2) const
82 {
83   int result;
84
85   result = MPI_IDENT;
86   if (size() != group2->size()) {
87     result = MPI_UNEQUAL;
88   } else {
89     for (int i = 0; i < size(); i++) {
90       int rank = group2->rank(actor(i));
91       if (rank == MPI_UNDEFINED) {
92         result = MPI_UNEQUAL;
93         break;
94       }
95       if (rank != i) {
96         result = MPI_SIMILAR;
97       }
98     }
99   }
100   return result;
101 }
102
103 int Group::incl(int n, const int* ranks, MPI_Group* newgroup) const
104 {
105   if (n == 0) {
106     *newgroup = MPI_GROUP_EMPTY;
107     return MPI_SUCCESS;
108   }
109
110   *newgroup = new Group(n);
111   for (int i = 0; i < n; i++) {
112     s4u::Actor* actor = this->actor(ranks[i]);
113     (*newgroup)->set_mapping(actor, i);
114   }
115   (*newgroup)->add_f();
116   return MPI_SUCCESS;
117 }
118
119 int Group::incl(const std::vector<int> ranks, MPI_Group* newgroup) const
120 {
121   return incl(static_cast<int>(ranks.size()), ranks.data(), newgroup);
122 }
123
124 int Group::excl(const std::vector<bool> excl_map, MPI_Group* newgroup) const
125 {
126   xbt_assert(static_cast<int>(excl_map.size()) == size());
127   std::vector<int> ranks;
128   for (int i = 0; i < static_cast<int>(excl_map.size()); i++)
129     if (not excl_map[i])
130       ranks.push_back(i);
131   return incl(static_cast<int>(ranks.size()), ranks.data(), newgroup);
132 }
133
134 int Group::group_union(const Group* group2, MPI_Group* newgroup) const
135 {
136   std::vector<int> ranks2;
137   for (int i = 0; i < group2->size(); i++) {
138     s4u::Actor* actor = group2->actor(i);
139     if (rank(actor) == MPI_UNDEFINED)
140       ranks2.push_back(i);
141   }
142
143   int newsize = size() + static_cast<int>(ranks2.size());
144   if (newsize == 0) {
145     *newgroup = MPI_GROUP_EMPTY;
146     return MPI_SUCCESS;
147   }
148
149   *newgroup = new Group(newsize);
150   int i;
151   for (i = 0; i < size(); i++) {
152     s4u::Actor* actor1 = actor(i);
153     (*newgroup)->set_mapping(actor1, i);
154   }
155   for (int j : ranks2) {
156     s4u::Actor* actor2 = group2->actor(j);
157     (*newgroup)->set_mapping(actor2, i);
158     i++;
159   }
160   (*newgroup)->add_f();
161   return MPI_SUCCESS;
162 }
163
164 int Group::intersection(const Group* group2, MPI_Group* newgroup) const
165 {
166   std::vector<int> ranks2;
167   for (int i = 0; i < group2->size(); i++) {
168     s4u::Actor* actor = group2->actor(i);
169     if (rank(actor) != MPI_UNDEFINED)
170       ranks2.push_back(i);
171   }
172   return group2->incl(ranks2, newgroup);
173 }
174
175 int Group::difference(const Group* group2, MPI_Group* newgroup) const
176 {
177   std::vector<int> ranks;
178   for (int i = 0; i < size(); i++) {
179     s4u::Actor* actor = this->actor(i);
180     if (group2->rank(actor) == MPI_UNDEFINED)
181       ranks.push_back(i);
182   }
183   return this->incl(ranks, newgroup);
184 }
185
186 int Group::excl(int n, const int* ranks, MPI_Group* newgroup) const
187 {
188   std::vector<bool> to_excl(size(), false);
189   for (int i = 0; i < n; i++)
190     to_excl[ranks[i]] = true;
191   return this->excl(to_excl, newgroup);
192 }
193
194 static bool is_rank_in_range(int rank, int first, int last)
195 {
196   return (first <= rank && rank <= last) || (first >= rank && rank >= last);
197 }
198
199 int Group::range_incl(int n, const int ranges[][3], MPI_Group* newgroup) const
200 {
201   std::vector<int> ranks;
202   for (int i = 0; i < n; i++) {
203     for (int j = ranges[i][0]; j >= 0 && j < size() && is_rank_in_range(j, ranges[i][0], ranges[i][1]);
204          j += ranges[i][2])
205       ranks.push_back(j);
206   }
207   return this->incl(ranks, newgroup);
208 }
209
210 int Group::range_excl(int n, const int ranges[][3], MPI_Group* newgroup) const
211 {
212   std::vector<bool> to_excl(size(), false);
213   for (int i = 0; i < n; i++) {
214     for (int j = ranges[i][0]; j >= 0 && j < size() && is_rank_in_range(j, ranges[i][0], ranges[i][1]);
215          j += ranges[i][2])
216       to_excl[j] = true;
217   }
218   return this->excl(to_excl, newgroup);
219 }
220
221 MPI_Group Group::f2c(int id) {
222   if(id == -2) {
223     return MPI_GROUP_EMPTY;
224   } else if (F2C::lookup() != nullptr && id >= 0) {
225     return static_cast<MPI_Group>(F2C::lookup()->at(id));
226   } else {
227     return MPI_GROUP_NULL;
228   }
229 }
230
231 }
232 }