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