Logo AND Algorithmique Numérique Distribuée

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