Logo AND Algorithmique Numérique Distribuée

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