a4cec69069
[SVN r41370]
139 lines
3.8 KiB
C++
139 lines
3.8 KiB
C++
// 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;
|
|
}
|