// 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) // A test of the gather() and gatherv() collectives. #include #include #include #include #include "gps_position.hpp" #include #include #include #include #define BOOST_TEST_MODULE mpi_gather #include using boost::mpi::communicator; template void gather_test(const communicator& comm, Generator generator, const char* kind, int root = -1) { typedef typename Generator::result_type value_type; value_type value = generator(comm.rank()); if (root == -1) { for (root = 0; root < comm.size(); ++root) gather_test(comm, generator, kind, root); } else { using boost::mpi::gather; std::vector values; if (comm.rank() == root) { std::cout << "Gathering " << kind << " from root " << root << "..." << std::endl; } gather(comm, value, values, root); if (comm.rank() == root) { std::vector expected_values; for (int p = 0; p < comm.size(); ++p) expected_values.push_back(generator(p)); BOOST_CHECK(values == expected_values); } else { BOOST_CHECK(values.empty()); } } (comm.barrier)(); } template void gatherv_test(const communicator& comm, Generator generator, const char* kind, int root = -1) { typedef typename Generator::result_type value_type; if (root == -1) { for (root = 0; root < comm.size(); ++root) gatherv_test(comm, generator, kind, root); } else { using boost::mpi::gatherv; int mysize = comm.rank() + 1; int nprocs = comm.size(); // process p will send p+1 identical generator(p) elements std::vector myvalues(mysize, generator(comm.rank())); if (comm.rank() == root) { std::vector values((nprocs*(nprocs+1))/2); std::vector sizes(comm.size()); for (int p = 0; p < comm.size(); ++p) sizes[p] = p + 1; std::cout << "Gatheringv " << kind << " from root " << root << "..." << std::endl; gatherv(comm, myvalues, &values[0], sizes, root); std::vector expected_values; for (int p = 0; p < comm.size(); ++p) for (int i = 0; i < p+1; ++i) expected_values.push_back(generator(p)); BOOST_CHECK(values == expected_values); } else { gatherv(comm, myvalues, root); } } (comm.barrier)(); } // // Generators to test with gather/gatherv // struct int_generator { typedef int result_type; int operator()(int p) const { return 17 + p; } }; struct gps_generator { typedef gps_position result_type; gps_position operator()(int p) const { return gps_position(39 + p, 16, 20.2799); } }; struct string_generator { typedef std::string result_type; std::string operator()(int p) const { std::string result = boost::lexical_cast(p); result += " rosebud"; if (p != 1) result += 's'; return result; } }; struct string_list_generator { typedef std::list result_type; std::list operator()(int p) const { std::list result; for (int i = 0; i <= p; ++i) { std::string value = boost::lexical_cast(i); result.push_back(value); } return result; } }; BOOST_AUTO_TEST_CASE(gather_check) { boost::mpi::environment env; communicator comm; gather_test(comm, int_generator(), "integers"); gather_test(comm, gps_generator(), "GPS positions"); gather_test(comm, string_generator(), "string"); gather_test(comm, string_list_generator(), "list of strings"); gatherv_test(comm, int_generator(), "integers"); gatherv_test(comm, gps_generator(), "GPS positions"); gatherv_test(comm, string_generator(), "string"); gatherv_test(comm, string_list_generator(), "list of strings"); }