Logo AND Algorithmique Numérique Distribuée

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