123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- // Copyright (C) 2006 Trustees of Indiana University
- //
- // Authors: Douglas Gregor
- // Andrew Lumsdaine
- // 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)
- // Performance test of the reduce() collective
- #include <boost/mpi.hpp>
- #include <boost/lexical_cast.hpp>
- namespace mpi = boost::mpi;
- struct add_int {
- int operator()(int x, int y) const { return x + y; }
- };
- struct wrapped_int
- {
- wrapped_int() : value(0) { }
- wrapped_int(int value) : value(value) { }
- template<typename Archiver>
- void serialize(Archiver& ar, const unsigned int /*version*/) {
- ar & value;
- }
- int value;
- };
- inline wrapped_int operator+(wrapped_int x, wrapped_int y)
- {
- return wrapped_int(x.value + y.value);
- }
- namespace boost { namespace mpi {
- template<> struct is_mpi_datatype<wrapped_int> : mpl::true_ { };
- } }
- struct serialized_int
- {
- serialized_int() : value(0) { }
- serialized_int(int value) : value(value) { }
- template<typename Archiver>
- void serialize(Archiver& ar, const unsigned int /*version*/) {
- ar & value;
- }
- int value;
- };
- inline serialized_int operator+(serialized_int x, serialized_int y)
- {
- return serialized_int(x.value + y.value);
- }
- int main(int argc, char* argv[])
- {
- mpi::environment env(argc, argv);
- mpi::communicator world;
- int repeat_count = 100;
- int outer_repeat_count = 2;
- if (argc > 1) repeat_count = boost::lexical_cast<int>(argv[1]);
- if (argc > 2) outer_repeat_count = boost::lexical_cast<int>(argv[2]);
- if (world.rank() == 0)
- std::cout << "# of processors: " << world.size() << std::endl
- << "# of iterations: " << repeat_count << std::endl;
- int value = world.rank();
- int result;
- wrapped_int wi_value = world.rank();
- wrapped_int wi_result;
- serialized_int si_value = world.rank();
- serialized_int si_result;
- // Spin for a while...
- for (int i = 0; i < repeat_count/10; ++i) {
- reduce(world, value, result, std::plus<int>(), 0);
- reduce(world, value, result, add_int(), 0);
- reduce(world, wi_value, wi_result, std::plus<wrapped_int>(), 0);
- reduce(world, si_value, si_result, std::plus<serialized_int>(), 0);
- }
- for (int outer = 0; outer < outer_repeat_count; ++outer) {
- // Raw MPI
- mpi::timer time;
- for (int i = 0; i < repeat_count; ++i) {
- MPI_Reduce(&value, &result, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
- }
- double reduce_raw_mpi_total_time = time.elapsed();
- // MPI_INT/MPI_SUM case
- time.restart();
- for (int i = 0; i < repeat_count; ++i) {
- reduce(world, value, result, std::plus<int>(), 0);
- }
- double reduce_int_sum_total_time = time.elapsed();
- // MPI_INT/MPI_Op case
- time.restart();
- for (int i = 0; i < repeat_count; ++i) {
- reduce(world, value, result, add_int(), 0);
- }
- double reduce_int_op_total_time = time.elapsed();
- // MPI_Datatype/MPI_Op case
- time.restart();
- for (int i = 0; i < repeat_count; ++i) {
- reduce(world, wi_value, wi_result, std::plus<wrapped_int>(), 0);
- }
- double reduce_type_op_total_time = time.elapsed();
-
- // Serialized/MPI_Op case
- time.restart();
- for (int i = 0; i < repeat_count; ++i) {
- reduce(world, si_value, si_result, std::plus<serialized_int>(), 0);
- }
- double reduce_ser_op_total_time = time.elapsed();
- if (world.rank() == 0)
- std::cout << "\nInvocation\tElapsed Time (seconds)"
- << "\nRaw MPI\t\t\t" << reduce_raw_mpi_total_time
- << "\nMPI_INT/MPI_SUM\t\t" << reduce_int_sum_total_time
- << "\nMPI_INT/MPI_Op\t\t" << reduce_int_op_total_time
- << "\nMPI_Datatype/MPI_Op\t" << reduce_type_op_total_time
- << "\nSerialized/MPI_Op\t" << reduce_ser_op_total_time
- << std::endl;
- }
- return 0;
- }
|