summaryrefslogtreecommitdiff
path: root/libs/mpi/src/communicator.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2013-06-25 22:59:01 +0000
committer <>2013-09-27 11:49:28 +0000
commit8c4528713d907ee2cfd3bfcbbad272c749867f84 (patch)
treec09e2ce80f47b90c85cc720f5139089ad9c8cfff /libs/mpi/src/communicator.cpp
downloadboost-tarball-baserock/morph.tar.gz
Imported from /home/lorry/working-area/delta_boost-tarball/boost_1_54_0.tar.bz2.boost_1_54_0baserock/morph
Diffstat (limited to 'libs/mpi/src/communicator.cpp')
-rw-r--r--libs/mpi/src/communicator.cpp322
1 files changed, 322 insertions, 0 deletions
diff --git a/libs/mpi/src/communicator.cpp b/libs/mpi/src/communicator.cpp
new file mode 100644
index 000000000..c1e145ca1
--- /dev/null
+++ b/libs/mpi/src/communicator.cpp
@@ -0,0 +1,322 @@
+// Copyright (C) 2005, 2006 Douglas Gregor.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+#include <boost/mpi/communicator.hpp>
+#include <boost/mpi/group.hpp>
+#include <boost/mpi/intercommunicator.hpp>
+#include <boost/mpi/graph_communicator.hpp>
+#include <boost/mpi/skeleton_and_content.hpp>
+#include <boost/mpi/detail/point_to_point.hpp>
+
+namespace boost { namespace mpi {
+
+/***************************************************************************
+ * status *
+ ***************************************************************************/
+bool status::cancelled() const
+{
+ int flag = 0;
+ BOOST_MPI_CHECK_RESULT(MPI_Test_cancelled, (&m_status, &flag));
+ return flag != 0;
+}
+
+/***************************************************************************
+ * communicator *
+ ***************************************************************************/
+
+communicator::communicator()
+{
+ comm_ptr.reset(new MPI_Comm(MPI_COMM_WORLD));
+}
+
+communicator::communicator(const MPI_Comm& comm, comm_create_kind kind)
+{
+ if (comm == MPI_COMM_NULL)
+ /* MPI_COMM_NULL indicates that the communicator is not usable. */
+ return;
+
+ switch (kind) {
+ case comm_duplicate:
+ {
+ MPI_Comm newcomm;
+ BOOST_MPI_CHECK_RESULT(MPI_Comm_dup, (comm, &newcomm));
+ comm_ptr.reset(new MPI_Comm(newcomm), comm_free());
+ MPI_Errhandler_set(newcomm, MPI_ERRORS_RETURN);
+ break;
+ }
+
+ case comm_take_ownership:
+ comm_ptr.reset(new MPI_Comm(comm), comm_free());
+ break;
+
+ case comm_attach:
+ comm_ptr.reset(new MPI_Comm(comm));
+ break;
+ }
+}
+
+communicator::communicator(const communicator& comm,
+ const boost::mpi::group& subgroup)
+{
+ MPI_Comm newcomm;
+ BOOST_MPI_CHECK_RESULT(MPI_Comm_create,
+ ((MPI_Comm)comm, (MPI_Group)subgroup, &newcomm));
+ comm_ptr.reset(new MPI_Comm(newcomm), comm_free());
+}
+
+int communicator::size() const
+{
+ int size_;
+ BOOST_MPI_CHECK_RESULT(MPI_Comm_size, (MPI_Comm(*this), &size_));
+ return size_;
+}
+
+int communicator::rank() const
+{
+ int rank_;
+ BOOST_MPI_CHECK_RESULT(MPI_Comm_rank, (MPI_Comm(*this), &rank_));
+ return rank_;
+}
+
+boost::mpi::group communicator::group() const
+{
+ MPI_Group gr;
+ BOOST_MPI_CHECK_RESULT(MPI_Comm_group, ((MPI_Comm)*this, &gr));
+ return boost::mpi::group(gr, /*adopt=*/true);
+}
+
+void communicator::send(int dest, int tag) const
+{
+ BOOST_MPI_CHECK_RESULT(MPI_Send,
+ (MPI_BOTTOM, 0, MPI_PACKED,
+ dest, tag, MPI_Comm(*this)));
+}
+
+status communicator::recv(int source, int tag) const
+{
+ status stat;
+ BOOST_MPI_CHECK_RESULT(MPI_Recv,
+ (MPI_BOTTOM, 0, MPI_PACKED,
+ source, tag, MPI_Comm(*this), &stat.m_status));
+ return stat;
+}
+
+optional<status> communicator::iprobe(int source, int tag) const
+{
+ typedef optional<status> result_type;
+
+ status stat;
+ int flag;
+ BOOST_MPI_CHECK_RESULT(MPI_Iprobe,
+ (source, tag, MPI_Comm(*this), &flag,
+ &stat.m_status));
+ if (flag) return stat;
+ else return result_type();
+}
+
+status communicator::probe(int source, int tag) const
+{
+ typedef optional<status> result_type;
+
+ status stat;
+ BOOST_MPI_CHECK_RESULT(MPI_Probe,
+ (source, tag, MPI_Comm(*this), &stat.m_status));
+ return stat;
+}
+
+void (communicator::barrier)() const
+{
+ BOOST_MPI_CHECK_RESULT(MPI_Barrier, (MPI_Comm(*this)));
+}
+
+
+communicator::operator MPI_Comm() const
+{
+ if (comm_ptr) return *comm_ptr;
+ else return MPI_COMM_NULL;
+}
+
+communicator communicator::split(int color) const
+{
+ return split(color, rank());
+}
+
+communicator communicator::split(int color, int key) const
+{
+ MPI_Comm newcomm;
+ BOOST_MPI_CHECK_RESULT(MPI_Comm_split,
+ (MPI_Comm(*this), color, key, &newcomm));
+ return communicator(newcomm, comm_take_ownership);
+}
+
+optional<intercommunicator> communicator::as_intercommunicator() const
+{
+ int flag;
+ BOOST_MPI_CHECK_RESULT(MPI_Comm_test_inter, ((MPI_Comm)*this, &flag));
+ if (flag)
+ return intercommunicator(comm_ptr);
+ else
+ return optional<intercommunicator>();
+}
+
+optional<graph_communicator> communicator::as_graph_communicator() const
+{
+ int status;
+ BOOST_MPI_CHECK_RESULT(MPI_Topo_test, ((MPI_Comm)*this, &status));
+ if (status == MPI_GRAPH)
+ return graph_communicator(comm_ptr);
+ else
+ return optional<graph_communicator>();
+}
+
+bool communicator::has_cartesian_topology() const
+{
+ int status;
+ BOOST_MPI_CHECK_RESULT(MPI_Topo_test, ((MPI_Comm)*this, &status));
+
+ return status == MPI_CART;
+}
+
+void communicator::abort(int errcode) const
+{
+ BOOST_MPI_CHECK_RESULT(MPI_Abort, (MPI_Comm(*this), errcode));
+}
+
+/*************************************************************
+ * archived send/recv *
+ *************************************************************/
+template<>
+void
+communicator::send<packed_oarchive>(int dest, int tag,
+ const packed_oarchive& ar) const
+{
+ detail::packed_archive_send(MPI_Comm(*this), dest, tag, ar);
+}
+
+template<>
+void
+communicator::send<packed_skeleton_oarchive>
+ (int dest, int tag, const packed_skeleton_oarchive& ar) const
+{
+ this->send(dest, tag, ar.get_skeleton());
+}
+
+template<>
+void communicator::send<content>(int dest, int tag, const content& c) const
+{
+ BOOST_MPI_CHECK_RESULT(MPI_Send,
+ (MPI_BOTTOM, 1, c.get_mpi_datatype(),
+ dest, tag, MPI_Comm(*this)));
+}
+
+template<>
+status
+communicator::recv<packed_iarchive>(int source, int tag,
+ packed_iarchive& ar) const
+{
+ status stat;
+ detail::packed_archive_recv(MPI_Comm(*this), source, tag, ar,
+ stat.m_status);
+ return stat;
+}
+
+template<>
+status
+communicator::recv<packed_skeleton_iarchive>
+ (int source, int tag, packed_skeleton_iarchive& ar) const
+{
+ return this->recv(source, tag, ar.get_skeleton());
+}
+
+template<>
+status
+communicator::recv<const content>(int source, int tag, const content& c) const
+{
+ status stat;
+ BOOST_MPI_CHECK_RESULT(MPI_Recv,
+ (MPI_BOTTOM, 1, c.get_mpi_datatype(),
+ source, tag, MPI_Comm(*this), &stat.m_status));
+ return stat;
+}
+
+/*************************************************************
+ * non-blocking send/recv *
+ *************************************************************/
+template<>
+request
+communicator::isend<packed_oarchive>(int dest, int tag,
+ const packed_oarchive& ar) const
+{
+ request req;
+ detail::packed_archive_isend(MPI_Comm(*this), dest, tag, ar,
+ &req.m_requests[0] ,2);
+ return req;
+}
+
+template<>
+request
+communicator::isend<packed_skeleton_oarchive>
+ (int dest, int tag, const packed_skeleton_oarchive& ar) const
+{
+ return this->isend(dest, tag, ar.get_skeleton());
+}
+
+template<>
+request communicator::isend<content>(int dest, int tag, const content& c) const
+{
+ request req;
+ BOOST_MPI_CHECK_RESULT(MPI_Isend,
+ (MPI_BOTTOM, 1, c.get_mpi_datatype(),
+ dest, tag, MPI_Comm(*this), &req.m_requests[0]));
+ return req;
+}
+
+request communicator::isend(int dest, int tag) const
+{
+ request req;
+ BOOST_MPI_CHECK_RESULT(MPI_Isend,
+ (MPI_BOTTOM, 0, MPI_PACKED,
+ dest, tag, MPI_Comm(*this), &req.m_requests[0]));
+ return req;
+}
+
+template<>
+request
+communicator::irecv<packed_skeleton_iarchive>
+ (int source, int tag, packed_skeleton_iarchive& ar) const
+{
+ return this->irecv(source, tag, ar.get_skeleton());
+}
+
+template<>
+request
+communicator::irecv<const content>(int source, int tag,
+ const content& c) const
+{
+ request req;
+ BOOST_MPI_CHECK_RESULT(MPI_Irecv,
+ (MPI_BOTTOM, 1, c.get_mpi_datatype(),
+ source, tag, MPI_Comm(*this), &req.m_requests[0]));
+ return req;
+}
+
+request communicator::irecv(int source, int tag) const
+{
+ request req;
+ BOOST_MPI_CHECK_RESULT(MPI_Irecv,
+ (MPI_BOTTOM, 0, MPI_PACKED,
+ source, tag, MPI_Comm(*this), &req.m_requests[0]));
+ return req;
+}
+
+bool operator==(const communicator& comm1, const communicator& comm2)
+{
+ int result;
+ BOOST_MPI_CHECK_RESULT(MPI_Comm_compare,
+ ((MPI_Comm)comm1, (MPI_Comm)comm2, &result));
+ return result == MPI_IDENT;
+}
+
+} } // end namespace boost::mpi