Logo AND Algorithmique Numérique Distribuée

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