From 9ddbac64c81ffcb7c643f75883413a4d7734d3aa Mon Sep 17 00:00:00 2001 From: Alain Miniussi Date: Thu, 4 Sep 2014 14:12:46 +0200 Subject: [PATCH] First incompomplete skectch of apossible cartesian communicator. --- include/boost/mpi/cartesian_communicator.hpp | 125 +++++++++++++++++++ src/cartesian_communicator.cpp | 27 ++++ test/cartesian_topology_test.cpp | 33 +++++ 3 files changed, 185 insertions(+) create mode 100644 include/boost/mpi/cartesian_communicator.hpp create mode 100644 src/cartesian_communicator.cpp create mode 100644 test/cartesian_topology_test.cpp diff --git a/include/boost/mpi/cartesian_communicator.hpp b/include/boost/mpi/cartesian_communicator.hpp new file mode 100644 index 0000000..d3da227 --- /dev/null +++ b/include/boost/mpi/cartesian_communicator.hpp @@ -0,0 +1,125 @@ +// Copyright (C) 2007 Trustees of Indiana University + +// Authors: Alain Miniussi + +// 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) + +/** @file cartesian_communicator.hpp + * + * This header defines facilities to support MPI communicators with + * cartesian topologies. + * If known at compiled time, the dimension of the implied grid + * can be statically enforced, through the templatized communicator + * class. Otherwise, a non template, dynamic, base class is provided. + * + */ +#ifndef BOOST_MPI_CARTESIAN_COMMUNICATOR_HPP +#define BOOST_MPI_CARTESIAN_COMMUNICATOR_HPP + +#include + +#include +#include + +// Headers required to implement cartesian topologies +#include +#include + +namespace boost { namespace mpi { + +/** + * @brief An MPI communicator with a cartesian topology. + * + * A @c cartesian_communicator is a communicator whose topology is + * expressed as a grid. Cartesian communicators have the same + * functionality as (intra)communicators, but also allow one to query + * the relationships among processes and the properties of the grid. + */ +class BOOST_MPI_DECL cartesian_communicator : public communicator +{ + friend class communicator; + + /** + * INTERNAL ONLY + * + * Construct a cartesian communicator given a shared pointer to the + * underlying MPI_Comm (which must have a cartesian topology). + * This operation is used for "casting" from a communicator to + * a cartesian communicator. + */ + explicit cartesian_communicator(const shared_ptr& comm_ptr) + : communicator() + { + this->comm_ptr = comm_ptr; + BOOST_ASSERT(has_cartesian_topology()); + } + +public: + /** + * Build a new Boost.MPI cartesian communicator based on the MPI + * communicator @p comm with cartesian topology. + * + * @p comm may be any valid MPI communicator. If @p comm is + * MPI_COMM_NULL, an empty communicator (that cannot be used for + * communication) is created and the @p kind parameter is + * ignored. Otherwise, the @p kind parameter determines how the + * Boost.MPI communicator will be related to @p comm: + * + * - If @p kind is @c comm_duplicate, duplicate @c comm to create + * a new communicator. This new communicator will be freed when + * the Boost.MPI communicator (and all copies of it) is + * destroyed. This option is only permitted if the underlying MPI + * implementation supports MPI 2.0; duplication of + * intercommunicators is not available in MPI 1.x. + * + * - If @p kind is @c comm_take_ownership, take ownership of @c + * comm. It will be freed automatically when all of the Boost.MPI + * communicators go out of scope. + * + * - If @p kind is @c comm_attach, this Boost.MPI communicator + * will reference the existing MPI communicator @p comm but will + * not free @p comm when the Boost.MPI communicator goes out of + * scope. This option should only be used when the communicator is + * managed by the user. + */ + cartesian_communicator(const MPI_Comm& comm, comm_create_kind kind) + : communicator(comm, kind) + { + BOOST_ASSERT(has_cartesian_topology()); + } + + /** + * Create a new communicator whose topology is described by the + * given cartesian. The indices of the vertices in the cartesian will be + * assumed to be the ranks of the processes within the + * communicator. There may be fewer vertices in the cartesian than + * there are processes in the communicator; in this case, the + * resulting communicator will be a NULL communicator. + * + * @param comm The communicator that the new, cartesian communicator + * will be based on. + * + * @param cartesian Any type that meets the requirements of the + * Incidence Cartesian and Vertex List Cartesian concepts from the Boost Cartesian + * Library. This structure of this cartesian will become the topology + * of the communicator that is returned. + * + * @param reorder Whether MPI is permitted to re-order the process + * ranks within the returned communicator, to better optimize + * communication. If false, the ranks of each process in the + * returned process will match precisely the rank of that process + * within the original communicator. + */ + cartesian_communicator(const communicator& comm, + const std::vector& dims, + const std::vector& periodic, + bool reorder = false); +}; + +} } // end namespace boost::mpi + + + +#endif // BOOST_MPI_CARTESIAN_COMMUNICATOR_HPP diff --git a/src/cartesian_communicator.cpp b/src/cartesian_communicator.cpp new file mode 100644 index 0000000..b46efda --- /dev/null +++ b/src/cartesian_communicator.cpp @@ -0,0 +1,27 @@ +// Copyright (C) 2014 Alain Miniussi. + +// 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 + +namespace boost { namespace mpi { + +cartesian_communicator::cartesian_communicator(const communicator& comm, + const std::vector& dims, + const std::vector& periodic, + bool reorder ) + : communicator() +{ + BOOST_ASSERT(dims.size() == periodic.size()); + MPI_Comm newcomm; + std::vector p(periodic.begin(), periodic.end()); + BOOST_MPI_CHECK_RESULT(MPI_Cart_create, + ((MPI_Comm)comm, dims.size(), + const_cast(dims.data()), p.data(), + int(reorder), &newcomm)); + if(newcomm != MPI_COMM_NULL) { + comm_ptr.reset(new MPI_Comm(newcomm), comm_free()); + } +} +} } // end namespace boost::mpi diff --git a/test/cartesian_topology_test.cpp b/test/cartesian_topology_test.cpp new file mode 100644 index 0000000..6b62a58 --- /dev/null +++ b/test/cartesian_topology_test.cpp @@ -0,0 +1,33 @@ +// Copyright (C) 2007 Trustees of Indiana University + +// Authors: Alain Miniussi + +// 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 + +#include +#include +#include + +#include + +namespace mpi = boost::mpi; + +int test_main(int argc, char* argv[]) +{ + mpi::environment env(argc, argv); + + mpi::communicator world; + std::vector dims(3); + std::vector periodic(3); + dims[0] = 2; dims[1] = 3; dims[2] = 4; + periodic[0] = true; periodic[1] = false; periodic[2] = true; + + mpi::cartesian_communicator cc(world, dims, periodic, true); + BOOST_CHECK(cc.has_cartesian_topology()); + + return 0; +}