]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/mpi/src/communicator.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / mpi / src / communicator.cpp
1 // Copyright (C) 2005, 2006 Douglas Gregor.
2
3 // Use, modification and distribution is subject to the Boost Software
4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 #include <boost/mpi/communicator.hpp>
7 #include <boost/mpi/group.hpp>
8 #include <boost/mpi/intercommunicator.hpp>
9 #include <boost/mpi/graph_communicator.hpp>
10 #include <boost/mpi/skeleton_and_content.hpp>
11 #include <boost/mpi/detail/point_to_point.hpp>
12
13 namespace boost { namespace mpi {
14
15 /***************************************************************************
16 * status *
17 ***************************************************************************/
18 bool status::cancelled() const
19 {
20 int flag = 0;
21 BOOST_MPI_CHECK_RESULT(MPI_Test_cancelled, (&m_status, &flag));
22 return flag != 0;
23 }
24
25 /***************************************************************************
26 * communicator *
27 ***************************************************************************/
28
29 communicator::communicator()
30 {
31 comm_ptr.reset(new MPI_Comm(MPI_COMM_WORLD));
32 }
33
34 communicator::communicator(const MPI_Comm& comm, comm_create_kind kind)
35 {
36 if (comm == MPI_COMM_NULL)
37 /* MPI_COMM_NULL indicates that the communicator is not usable. */
38 return;
39
40 switch (kind) {
41 case comm_duplicate:
42 {
43 MPI_Comm newcomm;
44 BOOST_MPI_CHECK_RESULT(MPI_Comm_dup, (comm, &newcomm));
45 comm_ptr.reset(new MPI_Comm(newcomm), comm_free());
46 MPI_Comm_set_errhandler(newcomm, MPI_ERRORS_RETURN);
47 break;
48 }
49
50 case comm_take_ownership:
51 comm_ptr.reset(new MPI_Comm(comm), comm_free());
52 break;
53
54 case comm_attach:
55 comm_ptr.reset(new MPI_Comm(comm));
56 break;
57 }
58 }
59
60 communicator::communicator(const communicator& comm,
61 const boost::mpi::group& subgroup)
62 {
63 MPI_Comm newcomm;
64 BOOST_MPI_CHECK_RESULT(MPI_Comm_create,
65 ((MPI_Comm)comm, (MPI_Group)subgroup, &newcomm));
66 if(newcomm != MPI_COMM_NULL)
67 comm_ptr.reset(new MPI_Comm(newcomm), comm_free());
68 }
69
70 int communicator::size() const
71 {
72 int size_;
73 BOOST_MPI_CHECK_RESULT(MPI_Comm_size, (MPI_Comm(*this), &size_));
74 return size_;
75 }
76
77 int communicator::rank() const
78 {
79 int rank_;
80 BOOST_MPI_CHECK_RESULT(MPI_Comm_rank, (MPI_Comm(*this), &rank_));
81 return rank_;
82 }
83
84 boost::mpi::group communicator::group() const
85 {
86 MPI_Group gr;
87 BOOST_MPI_CHECK_RESULT(MPI_Comm_group, ((MPI_Comm)*this, &gr));
88 return boost::mpi::group(gr, /*adopt=*/true);
89 }
90
91 void communicator::send(int dest, int tag) const
92 {
93 BOOST_MPI_CHECK_RESULT(MPI_Send,
94 (MPI_BOTTOM, 0, MPI_PACKED,
95 dest, tag, MPI_Comm(*this)));
96 }
97
98 status communicator::recv(int source, int tag) const
99 {
100 status stat;
101 BOOST_MPI_CHECK_RESULT(MPI_Recv,
102 (MPI_BOTTOM, 0, MPI_PACKED,
103 source, tag, MPI_Comm(*this), &stat.m_status));
104 return stat;
105 }
106
107 optional<status> communicator::iprobe(int source, int tag) const
108 {
109 typedef optional<status> result_type;
110
111 status stat;
112 int flag;
113 BOOST_MPI_CHECK_RESULT(MPI_Iprobe,
114 (source, tag, MPI_Comm(*this), &flag,
115 &stat.m_status));
116 if (flag) return stat;
117 else return result_type();
118 }
119
120 status communicator::probe(int source, int tag) const
121 {
122 status stat;
123 BOOST_MPI_CHECK_RESULT(MPI_Probe,
124 (source, tag, MPI_Comm(*this), &stat.m_status));
125 return stat;
126 }
127
128 void (communicator::barrier)() const
129 {
130 BOOST_MPI_CHECK_RESULT(MPI_Barrier, (MPI_Comm(*this)));
131 }
132
133
134 communicator::operator MPI_Comm() const
135 {
136 if (comm_ptr) return *comm_ptr;
137 else return MPI_COMM_NULL;
138 }
139
140 communicator communicator::split(int color) const
141 {
142 return split(color, rank());
143 }
144
145 communicator communicator::split(int color, int key) const
146 {
147 MPI_Comm newcomm;
148 BOOST_MPI_CHECK_RESULT(MPI_Comm_split,
149 (MPI_Comm(*this), color, key, &newcomm));
150 return communicator(newcomm, comm_take_ownership);
151 }
152
153 optional<intercommunicator> communicator::as_intercommunicator() const
154 {
155 int flag;
156 BOOST_MPI_CHECK_RESULT(MPI_Comm_test_inter, ((MPI_Comm)*this, &flag));
157 if (flag)
158 return intercommunicator(comm_ptr);
159 else
160 return optional<intercommunicator>();
161 }
162
163 optional<graph_communicator> communicator::as_graph_communicator() const
164 {
165 optional<graph_communicator> graph;
166 // topology test not allowed on MPI_NULL_COMM
167 if (bool(*this)) {
168 int status;
169 BOOST_MPI_CHECK_RESULT(MPI_Topo_test, ((MPI_Comm)*this, &status));
170 if (status == MPI_GRAPH)
171 graph = graph_communicator(comm_ptr);
172 }
173 return graph;
174 }
175
176 bool communicator::has_cartesian_topology() const
177 {
178 // topology test not allowed on MPI_NULL_COM
179 if (!bool(*this)) {
180 return false;
181 } else {
182 int status;
183 BOOST_MPI_CHECK_RESULT(MPI_Topo_test, ((MPI_Comm)*this, &status));
184 return status == MPI_CART;
185 }
186 }
187
188 void communicator::abort(int errcode) const
189 {
190 BOOST_MPI_CHECK_RESULT(MPI_Abort, (MPI_Comm(*this), errcode));
191 }
192
193 /*************************************************************
194 * archived send/recv *
195 *************************************************************/
196 template<>
197 void
198 communicator::send<packed_oarchive>(int dest, int tag,
199 const packed_oarchive& ar) const
200 {
201 detail::packed_archive_send(MPI_Comm(*this), dest, tag, ar);
202 }
203
204 template<>
205 void
206 communicator::send<packed_skeleton_oarchive>
207 (int dest, int tag, const packed_skeleton_oarchive& ar) const
208 {
209 this->send(dest, tag, ar.get_skeleton());
210 }
211
212 template<>
213 void communicator::send<content>(int dest, int tag, const content& c) const
214 {
215 BOOST_MPI_CHECK_RESULT(MPI_Send,
216 (MPI_BOTTOM, 1, c.get_mpi_datatype(),
217 dest, tag, MPI_Comm(*this)));
218 }
219
220 template<>
221 status
222 communicator::recv<packed_iarchive>(int source, int tag,
223 packed_iarchive& ar) const
224 {
225 status stat;
226 detail::packed_archive_recv(MPI_Comm(*this), source, tag, ar,
227 stat.m_status);
228 return stat;
229 }
230
231 template<>
232 status
233 communicator::recv<packed_skeleton_iarchive>
234 (int source, int tag, packed_skeleton_iarchive& ar) const
235 {
236 return this->recv(source, tag, ar.get_skeleton());
237 }
238
239 template<>
240 status
241 communicator::recv<const content>(int source, int tag, const content& c) const
242 {
243 status stat;
244 BOOST_MPI_CHECK_RESULT(MPI_Recv,
245 (MPI_BOTTOM, 1, c.get_mpi_datatype(),
246 source, tag, MPI_Comm(*this), &stat.m_status));
247 return stat;
248 }
249
250 /*************************************************************
251 * non-blocking send/recv *
252 *************************************************************/
253 template<>
254 request
255 communicator::isend<packed_oarchive>(int dest, int tag,
256 const packed_oarchive& ar) const
257 {
258 request req;
259 detail::packed_archive_isend(MPI_Comm(*this), dest, tag, ar,
260 &req.m_requests[0] ,2);
261 return req;
262 }
263
264 template<>
265 request
266 communicator::isend<packed_skeleton_oarchive>
267 (int dest, int tag, const packed_skeleton_oarchive& ar) const
268 {
269 return this->isend(dest, tag, ar.get_skeleton());
270 }
271
272 template<>
273 request communicator::isend<content>(int dest, int tag, const content& c) const
274 {
275 request req;
276 BOOST_MPI_CHECK_RESULT(MPI_Isend,
277 (MPI_BOTTOM, 1, c.get_mpi_datatype(),
278 dest, tag, MPI_Comm(*this), &req.m_requests[0]));
279 return req;
280 }
281
282 request communicator::isend(int dest, int tag) const
283 {
284 request req;
285 BOOST_MPI_CHECK_RESULT(MPI_Isend,
286 (MPI_BOTTOM, 0, MPI_PACKED,
287 dest, tag, MPI_Comm(*this), &req.m_requests[0]));
288 return req;
289 }
290
291 template<>
292 request
293 communicator::irecv<packed_skeleton_iarchive>
294 (int source, int tag, packed_skeleton_iarchive& ar) const
295 {
296 return this->irecv(source, tag, ar.get_skeleton());
297 }
298
299 template<>
300 request
301 communicator::irecv<const content>(int source, int tag,
302 const content& c) const
303 {
304 request req;
305 BOOST_MPI_CHECK_RESULT(MPI_Irecv,
306 (MPI_BOTTOM, 1, c.get_mpi_datatype(),
307 source, tag, MPI_Comm(*this), &req.m_requests[0]));
308 return req;
309 }
310
311 request communicator::irecv(int source, int tag) const
312 {
313 request req;
314 BOOST_MPI_CHECK_RESULT(MPI_Irecv,
315 (MPI_BOTTOM, 0, MPI_PACKED,
316 source, tag, MPI_Comm(*this), &req.m_requests[0]));
317 return req;
318 }
319
320 bool operator==(const communicator& comm1, const communicator& comm2)
321 {
322 int result;
323 BOOST_MPI_CHECK_RESULT(MPI_Comm_compare,
324 ((MPI_Comm)comm1, (MPI_Comm)comm2, &result));
325 return result == MPI_IDENT;
326 }
327
328 } } // end namespace boost::mpi